Compare commits

...

267 Commits

Author SHA1 Message Date
Subv
20d86d8a36 GPU: Partially implemented the Fermi2D surface copy operation.
The hardware allows for some rather complicated operations to be performed on the data during the copy, this is not implemented.
Only same-format same-size raw copies are implemented for now.
2018-04-25 12:54:26 -05:00
Subv
5ab597041f Memory: Added a missing shortcut for Memory::CopyBlock for the current process. 2018-04-25 11:55:30 -05:00
Subv
1dd4861d38 GPU: Make the Textures::CopySwizzledData function accessible from the outside of the file. 2018-04-25 11:55:30 -05:00
Subv
a6da2b93c1 GPU: Added a function to retrieve the bytes per pixel of the render target formats. 2018-04-25 11:55:29 -05:00
Subv
378c881427 GPU: Added surface copy registers to Fermi2D 2018-04-25 11:55:29 -05:00
Subv
b1109931b9 GPU: Added boilerplate code for the Fermi2D engine 2018-04-25 11:55:29 -05:00
Subv
c16cfbbc6c GPU: Reduce the number of registers of Maxwell3D to 0xE00.
The rest are just macro shim registers.
2018-04-25 11:55:28 -05:00
Subv
a994446b6e GPU: Move the Maxwell3D macro uploading code to the inside of the Maxwell3D processor.
It doesn't belong in the PFIFO handler.
2018-04-25 11:55:27 -05:00
Subv
e2f2a49d2d GPU: Corrected the upper bound of the PFIFO method ids in the command processor. 2018-04-25 11:53:54 -05:00
bunnei
22420612db Merge pull request #394 from lioncash/video-core
video-core: Move logging macros over to new fmt-capable ones
2018-04-25 11:42:59 -04:00
Lioncash
b7551e457b video-core: Move logging macros over to new fmt-capable ones 2018-04-25 09:13:57 -04:00
bunnei
ea3151f475 Merge pull request #388 from bunnei/refactor-rasterizer-cache
Refactor rasterizer cache
2018-04-24 23:22:24 -04:00
bunnei
6c9ca8cbca Merge pull request #393 from lioncash/loader
loader: Move old logging macros over to new fmt-capable ones
2018-04-24 22:44:18 -04:00
bunnei
c30cd898fc renderer_opengl: Use correct byte order for framebuffer pixel format ABGR8. 2018-04-24 22:31:46 -04:00
bunnei
f1a4a004fb gl_rasterizer_cache: Use CHAR_BIT for bpp conversions instead of 8. 2018-04-24 22:31:46 -04:00
bunnei
0a023cfb4f gl_rasterizer_cache: Use GPU PAGE_BITS/SIZE, not CPU. 2018-04-24 22:31:46 -04:00
bunnei
9022d926eb gl_rasterizer_cache: Use new logger. 2018-04-24 22:31:46 -04:00
bunnei
fbb3cd110c gl_rasterizer_cache: Add a function for finding framebuffer GPU address. 2018-04-24 22:31:46 -04:00
bunnei
bc0f1896fc gl_rasterizer_cache: Handle compressed texture sizes. 2018-04-24 22:31:46 -04:00
bunnei
4415e00181 gl_rasterizer_cache: Update to be based on GPU addresses, not CPU addresses. 2018-04-24 22:31:45 -04:00
Lioncash
cc2e14ec2a loader: Move old logging macros over to new fmt-capable ones 2018-04-24 20:22:32 -04:00
bunnei
10c6d89119 memory_manager: Add implement CpuToGpuAddress. 2018-04-24 17:49:20 -04:00
bunnei
239ac8abe2 memory_manager: Make GpuToCpuAddress return an optional. 2018-04-24 17:49:19 -04:00
bunnei
9e11a76e92 memory_manager: Use GPUVAdddr, not PAddr, for GPU addresses. 2018-04-24 17:40:43 -04:00
bunnei
e8c2bb24b2 Merge pull request #386 from Subv/gpu_query
GPU: Added asserts to our code for handling the QUERY_GET GPU command.
2018-04-24 16:13:51 -04:00
bunnei
b7953d2ebf Merge pull request #392 from lioncash/log
service: Move logging macros over to the new fmt-compatible ones
2018-04-24 14:13:54 -04:00
Lioncash
d08cfb55fe service: Move logging macros over to new fmt-compatible ones 2018-04-24 12:01:32 -04:00
Lioncash
88eb612718 vi: Move logging macros over to new fmt-compatible ones 2018-04-24 12:01:31 -04:00
Lioncash
bd9c2aa51f time: Move logging macros over to new fmt-compatible ones 2018-04-24 12:01:31 -04:00
Lioncash
bfe49edb2a ssl: Move logging macros over to new fmt-compatible ones 2018-04-24 12:01:31 -04:00
Lioncash
82413a6c89 spl: Move logging macros over to new fmt-compatible ones 2018-04-24 12:01:31 -04:00
Lioncash
62c69f4a1e sockets: Move logging macros over to new fmt-compatible ones 2018-04-24 12:01:31 -04:00
Lioncash
2a3f3bf977 sm: Move logging macros over to new fmt-compatible ones 2018-04-24 12:01:31 -04:00
Lioncash
32ece18bb6 set: Move logging macros over to new fmt-compatible ones 2018-04-24 12:01:30 -04:00
Lioncash
13f9cf2bd0 pctl: Move logging macros over to new fmt-compatible ones 2018-04-24 12:01:30 -04:00
Lioncash
72b497e876 nvflinger: Move logging macros over to new fmt-compatible ones 2018-04-24 12:01:30 -04:00
Lioncash
285d8d8b7d nvdrv: Move logging macros over to new fmt-compatible ones 2018-04-24 12:01:27 -04:00
Lioncash
022fc59dcd ns: Move logging macros over to new fmt-compatible ones 2018-04-24 12:00:56 -04:00
Lioncash
47054327c2 nifm: Move logging macros over to new fmt-compatible ones 2018-04-24 12:00:56 -04:00
Lioncash
28b92db7fd nfp: Move logging macros over to new fmt-compatible ones 2018-04-24 12:00:56 -04:00
Lioncash
dabfd90dfe lm: Move logging macros over to new fmt-compatible ones 2018-04-24 12:00:56 -04:00
Lioncash
9cd7485cd7 hid: Move logging macros over to new fmt-compatible ones 2018-04-24 12:00:56 -04:00
Lioncash
8fc4003dab friend: Move logging macros over to new fmt-compatible ones 2018-04-24 12:00:56 -04:00
Lioncash
b5b613ea29 filesystem: Move logging macros over to new fmt-compatible ones 2018-04-24 12:00:52 -04:00
bunnei
299f943202 Merge pull request #391 from lioncash/video
renderer_opengl: Silence a -Wdangling-else warning in DrawScreenTriangles()
2018-04-24 11:54:44 -04:00
Lioncash
d1b23b2b51 renderer_opengl: Silence a -Wdangling-else warning in DrawScreenTriangles() 2018-04-24 11:13:08 -04:00
Lioncash
c6a740d7c2 fatal: Move logging macros over to new fmt-compatible ones 2018-04-24 10:18:58 -04:00
Lioncash
8d32bf9a96 audio: Move logging macros over to new fmt-compatible ones 2018-04-24 10:18:09 -04:00
Lioncash
d652e41365 apm: Move logging macros over to new fmt-compatible ones 2018-04-24 10:16:03 -04:00
Lioncash
e74dbfc572 aoc: Move logging macros over to new fmt-compatible ones 2018-04-24 10:14:52 -04:00
Lioncash
5483c08b44 am: Move logging macros over to new fmt-compatible ones 2018-04-24 10:14:11 -04:00
Lioncash
f85d880ac6 acc: Move logging macros over to new fmt-compatible ones 2018-04-24 10:04:22 -04:00
bunnei
7495142688 Merge pull request #389 from mailwl/fs-renamefile
Service/FS: implement IFileSystem::RenameFile
2018-04-24 08:57:46 -04:00
mailwl
a0179e5ca5 Service/FS: implement IFileSystem::RenameFile 2018-04-24 10:56:05 +03:00
bunnei
07dc0bbf3e Merge pull request #379 from Subv/multi_buffers
GPU: Support multiple enabled vertex arrays.
2018-04-24 01:09:02 -04:00
Subv
f208953585 GPU: Added asserts to our code for handling the QUERY_GET GPU command.
This is based on research from nouveau. Many things are currently unknown and will require hwtests in the future.
This commit also stubs QueryMode::Write2 to do the same as Write. Nouveau code treats them interchangeably, it is currently unknown what the difference is.
2018-04-23 17:06:57 -05:00
bunnei
0214351f4f Merge pull request #370 from Subv/sync_primitives
Kernel: Reworked the new kernel synchronization primitives.
2018-04-23 16:33:00 -04:00
bunnei
bf25299272 Merge pull request #384 from Subv/nvhost-remap
Nvdrv/nvhost-as-gpu: Implemented the ioctl REMAP command.
2018-04-23 15:23:55 -04:00
bunnei
d4f87e9af4 Merge pull request #385 from Subv/unimpl_ioctls
Nvdrv: Assert when receiving an unimplemented ioctl in the nv* handlers.
2018-04-23 15:22:49 -04:00
bunnei
3967f9c6ef Merge pull request #383 from Subv/gpu_mmu
GPU: Make the GPU virtual memory manager use 16 page bits and 10 pagetable bits.
2018-04-23 14:00:52 -04:00
bunnei
55d0b0609d Merge pull request #382 from Subv/a2rgb10_rt
GPU: Implement the RGB10_A2 RenderTarget format
2018-04-23 13:16:48 -04:00
Subv
9531a29283 GPU: Support multiple enabled vertex arrays.
The vertex arrays will be copied to the stream buffer one after the other, and the attributes will be set using the ARB_vertex_attrib_binding extension.

yuzu now thus requires OpenGL 4.3 or the ARB_vertex_attrib_binding extension.
2018-04-23 11:34:50 -05:00
Subv
46572d027d Kernel: Implemented mutex priority inheritance.
Verified with a hwtest and implemented based on reverse engineering.

Thread A's priority will get bumped to the highest priority among all the threads that are waiting for a mutex that A holds.
Once A releases the mutex and ownership is transferred to B, A's priority will return to normal and B's priority will be bumped.
2018-04-23 11:23:44 -05:00
Subv
0d6eafe11a NvDrv/nvhost-as-gpu: Ensure that the object passed to MapBufferEx has already been allocated.
Also added a consistency check and a comment for the case when the object id is different than its handle. The real nvservices doesn't make a distinction between ids and handles, each object gets an unique handle which doubles as its id.
2018-04-23 11:21:46 -05:00
Subv
e4bd0bddea Nvdrv/nvhost-as-gpu: Implemented the ioctl REMAP command.
It takes a previously-reserved (AllocateSpace) GPU memory address and maps it to the address of the nvmap object passed to Remap.
2018-04-23 11:21:46 -05:00
Subv
e862c50a70 Nvdrv: Assert when receiving an unimplemented ioctl in the nv* handlers. 2018-04-23 11:13:53 -05:00
Subv
f823c1d599 GPU: Make the GPU virtual memory manager use 16 page bits and 10 page table bits.
Also removed some dead code and added memory map consistency asserts.
2018-04-23 10:57:12 -05:00
Subv
010227e149 GPU: Implement the RGB10_A2 RenderTarget format, it will use the same format as the A2BGR10 texture format. 2018-04-23 10:50:28 -05:00
bunnei
ebb8e06df0 Merge pull request #378 from Subv/a2bgr10
GPU: Implement the A2BGR10 texture format.
2018-04-21 21:43:17 -04:00
Subv
c079cf4eec GPU: Implement the A2BGR10 texture format. 2018-04-21 17:32:25 -05:00
bunnei
62937798a0 Merge pull request #377 from adityaruplaha/sdl2-fullscreen
SDL2: Implement fullscreen. (Original PR: citra-emu/citra#3607)
2018-04-21 13:53:55 -04:00
adityaruplaha
f48d5e4c4c SDL2: Implement fullscreen. (Original PR: citra-emu/citra#3607) 2018-04-21 13:24:33 +05:30
bunnei
f8764bb5d3 Merge pull request #376 from bunnei/shader-decoder
Shader opcode decoding
2018-04-21 00:04:51 -04:00
bunnei
f8a037ead4 Merge pull request #375 from lioncash/header
opengl: Remove unnecessary header inclusions
2018-04-20 23:08:47 -04:00
bunnei
d08fd7e86d gl_shader_decompiler: Skip RRO instruction. 2018-04-20 22:30:56 -04:00
bunnei
8b28dc55e6 gl_shader_decompiler: Cleanup error logging. 2018-04-20 22:30:56 -04:00
bunnei
e1630c4d43 shader_bytecode: Add several more instruction decodings. 2018-04-20 22:30:56 -04:00
bunnei
9f6d305eab shader_bytecode: Decode instructions based on bit strings. 2018-04-20 22:30:56 -04:00
bunnei
8ac3a3f45e Merge pull request #369 from Subv/shader_instr2
ShaderGen: Implemented fsetp/kil and predicated instruction execution.
2018-04-20 22:29:39 -04:00
bunnei
634d9ee18b Merge pull request #374 from lioncash/noexcept
gl_resource_manager: Add missing noexcept specifiers to move constructors and assignment operators
2018-04-20 22:28:47 -04:00
bunnei
ba6f3e8f9f Merge pull request #373 from lioncash/enum2
gl_rasterizer_cache: Make MatchFlags an enum class
2018-04-20 22:28:09 -04:00
Subv
17a0ef1e1e ShaderGen: Implemented the KIL instruction, which is equivalent to 'discard'. 2018-04-20 21:09:34 -05:00
Subv
c3a8ea76f1 ShaderGen: Implemented predicated instruction execution.
Each predicated instruction will be wrapped in an `if (predicate) { instruction_body; }` in the GLSL, where `predicate` is one of the predicate boolean variables previously set by fsetp.
2018-04-20 21:09:33 -05:00
Subv
0a5e01b710 ShaderGen: Implemented the fsetp instruction.
Predicate variables are now added to the generated shader code in the form of 'pX' where X is the predicate id.
These predicate variables are initialized to false on shader startup and are set via the fsetp instructions.

TODO:

* Not all the comparison types are implemented.
* Only the single-predicate version is implemented.
2018-04-20 21:09:33 -05:00
Subv
a70ed9c8ae Kernel: Use 0x2C as default main thread priority for homebrew and lone NRO/NSOs 2018-04-20 21:04:35 -05:00
Subv
013778aa21 Qt: Update the WaitTree widget to show info about the current mutex of each thread. 2018-04-20 21:04:34 -05:00
Subv
be155f4d9d Kernel: Remove unused ConditionVariable class. 2018-04-20 21:04:33 -05:00
Subv
5fdfbfe25a Kernel: Remove old and unused Mutex code. 2018-04-20 21:04:32 -05:00
Subv
b18ccf9399 Kernel: Properly implemented svcWaitProcessWideKey and svcSignalProcessWideKey
They work in tandem with guest code to provide synchronization primitives along with svcArbitrateLock/Unlock
2018-04-20 21:04:27 -05:00
Subv
e81a2080eb Kernel: Corrected the implementation of svcArbitrateLock and svcArbitrateUnlock.
Switch mutexes are no longer kernel objects, they are managed in userland and only use the kernel to handle the contention case.
Mutex addresses store a special flag value (0x40000000) to notify the guest code that there are still some threads waiting for the mutex to be released. This flag is updated when a thread calls ArbitrateUnlock.

TODO:
* Fix svcWaitProcessWideKey
* Fix svcSignalProcessWideKey
* Remove the Mutex class.
2018-04-20 21:04:25 -05:00
bunnei
1723b4d8d4 Merge pull request #372 from lioncash/enum
resource_limit: Make ResourceTypes an enum class
2018-04-20 21:26:54 -04:00
bunnei
2e7ce96b1d Merge pull request #371 from lioncash/global
core: Relocate g_service_manager to the System class
2018-04-20 21:26:27 -04:00
Lioncash
eafdcc1b8a opengl: Remove unnecessary header inclusions 2018-04-20 20:19:37 -04:00
Lioncash
ab71997b2c gl_resource_manager: Add missing noexcept specifiers to move constructors and assignment operators
Standard library containers may use std::move_if_noexcept to perform
move operations. If a move cannot be performed under these
circumstances, then a copy is attempted. Given we only intend for these
types to be move-only this can be somewhat problematic. By defining
these to be noexcept we prevent cases where copies may be attempted.
2018-04-20 20:04:00 -04:00
Lioncash
7db0b8d74f gl_rasterizer_cache: Make MatchFlags an enum class
Prevents implicit conversions and scope pollution.
2018-04-20 19:50:05 -04:00
Lioncash
659a612368 core: Relocate g_service_manager to the System class
Converts the service manager from a global into an instance-based
variable.
2018-04-20 19:44:32 -04:00
Lioncash
bec05db746 resource_limit: Make ResourceTypes an enum class
Prevents enum identifiers from leaking into the surrounding scope.
2018-04-20 19:41:45 -04:00
bunnei
1df3a7710e Merge pull request #340 from mailwl/vi-update
Service/VI: stub SetLayerVisibility, fix GetDisplayResolution output
2018-04-20 16:23:15 -04:00
Subv
d03fc77475 ShaderGen: Register id 255 is special and is hardcoded to return 0 (SR_ZERO). 2018-04-20 14:57:40 -05:00
Subv
2e0a9f66a0 ShaderGen: Ignore the 'sched' instruction when generating shaders.
The 'sched' instruction has a very convoluted encoding, but fortunately it seems to only appear on a fixed interval (once every 4 instructions).
2018-04-20 14:57:40 -05:00
bunnei
326b044c19 Merge pull request #367 from lioncash/clamp
math_util: Remove the Clamp() function
2018-04-20 14:18:03 -04:00
bunnei
87f89ac82d Merge pull request #361 from lioncash/common
common_types: Minor changes
2018-04-20 10:27:17 -04:00
Lioncash
fae2dd0344 math_util: Remove the Clamp() function
C++17 adds clamp() to the standard library, so we can remove ours in
favor of it.
2018-04-20 10:14:13 -04:00
bunnei
a904d70afe Merge pull request #368 from lioncash/dynarmic
externals: Update dynarmic to HEAD
2018-04-20 09:48:15 -04:00
bunnei
b11f6f90e7 Merge pull request #360 from lioncash/namespaces
service: Use nested namespace specifiers where applicable
2018-04-20 09:44:40 -04:00
bunnei
4d96997447 Merge pull request #364 from lioncash/thread-local
common/thread: Remove unnecessary feature checking for thread_local
2018-04-20 09:43:52 -04:00
bunnei
b5c204ac6f Merge pull request #362 from lioncash/snprintf
common_funcs: Remove check for VS versions that we don't even support
2018-04-20 09:43:30 -04:00
bunnei
701dd649e6 Merge pull request #363 from lioncash/array-size
common_funcs: Remove ARRAY_SIZE macro
2018-04-20 09:43:02 -04:00
bunnei
79c1ed80e9 Merge pull request #366 from lioncash/vec
vector_math: Remove AsArray() and Write() functions from Vec[2,3,4]
2018-04-20 09:42:41 -04:00
bunnei
cb267093bb Merge pull request #365 from lioncash/codeblock
common: Remove code_block.h
2018-04-20 09:42:15 -04:00
Lioncash
b2febaff2f externals: Update dynarmic to HEAD 2018-04-20 09:02:18 -04:00
Lioncash
956e200f12 vector_math: Remove AsArray() and Write() functions from Vec[2,3,4]
These are all unused and the Write() ones should arguably not even be in the interface. There are better ways to provide this if we ever need it (like iterators).
2018-04-19 22:58:24 -04:00
Lioncash
0eba5911f2 common: Remove code_block.h
We use dynarmic, so this is unued. Anything else we need will likely use Xbyak, so
this header isn't necessary any more.
2018-04-19 22:47:02 -04:00
Lioncash
b134e6afcf common/thread: Remove unnecessary feature checking for thread_local
Every compiler we require already supports it.
2018-04-19 22:41:18 -04:00
Lioncash
d9e316e353 common_funcs: Remove ARRAY_SIZE macro
C++17 has non-member size() which we can just call where necessary.
2018-04-19 22:36:52 -04:00
Lioncash
902fc61ef8 common_funcs: Remove check for VS versions that we don't even support
We don't support any VS versions that don't already have snprintf in the
standard library implementation.
2018-04-19 22:28:56 -04:00
Lioncash
16ffecd8fb common_types: Convert typedefs to using aliases
May as well while we're making changes to this file.
2018-04-19 22:26:35 -04:00
Lioncash
e8e5041955 common_types: Remove unnecessary check for whether or not__func__ is defined
VS has supported this for quite a while.
2018-04-19 22:25:19 -04:00
Lioncash
ccca5e7c28 service: Use nested namespace specifiers where applicable
Tidies up namespace declarations
2018-04-19 22:20:28 -04:00
bunnei
2c8afe1140 Merge pull request #357 from lioncash/guard
renderer_opengl: Add missing header guards
2018-04-19 22:17:25 -04:00
bunnei
2ef04f69b2 Merge pull request #358 from lioncash/explicit
disk_filesystem: Minor changes
2018-04-19 22:16:55 -04:00
bunnei
14bf88a777 Merge pull request #359 from lioncash/redundant
vi: Remove redundant initializers in the constructors
2018-04-19 22:16:17 -04:00
Lioncash
3990da488b vi: Remove redundant initializers in the constructors 2018-04-19 21:34:36 -04:00
Lioncash
80982748c8 disk_filesystem: Remove unused total_entries_in_directory member from Disk_Directory 2018-04-19 21:28:56 -04:00
Lioncash
e61a4dd485 disk_filesystem: Remove redundant initializer in Disk_Directory's constructor 2018-04-19 21:28:07 -04:00
Lioncash
b05f8ea5b5 disk_filesystem: Make constructors explicit where applicable 2018-04-19 21:27:43 -04:00
Lioncash
3841ec4200 renderer_opengl: Add missing header guards 2018-04-19 21:13:59 -04:00
bunnei
17ad56c1dc Merge pull request #356 from lioncash/shader
glsl_shader_decompiler: Minor API changes to ShaderWriter
2018-04-19 21:09:25 -04:00
bunnei
f633b0c875 Merge pull request #355 from Subv/shader_instr
ShaderGen: Fixed TEXS overriding its own texcoords and implemented fmul32i
2018-04-19 21:09:02 -04:00
Lioncash
e3b6f6c016 glsl_shader_decompiler: Use std::string_view instead of std::string for AddLine()
This function doesn't need to take ownership of the string data being
given to it, considering all we do is append the characters to the
internal string instance.

Instead, use a string view to simply reference the string data without
any potential heap allocation.

Now anything that is a raw const char* won't need to be converted to a
std::string before appending.
2018-04-19 20:12:58 -04:00
Lioncash
412b31ad72 glsl_shader_decompiler: Add AddNewLine() function to ShaderWriter
Avoids constructing a std::string just to append a newline character
2018-04-19 20:09:27 -04:00
Lioncash
aa26baa3db glsl_shader_decompiler: Add char overload for ShaderWriter's AddLine()
Avoids constructing a std::string just to append a character.
2018-04-19 20:04:09 -04:00
Lioncash
4ef392906b glsl_shader_decompiler: Append indentation without constructing a separate std::string
The interface of std::string already lets us append N copies of a
character to an existing string.
2018-04-19 19:59:25 -04:00
James Rowe
3f49210234 Merge pull request #348 from jlachniet/patch-1
Technically, yuzu can boot commercial games
2018-04-19 14:07:17 -06:00
Subv
fe84842137 ShaderGen: Implemented the fmul32i shader instruction. 2018-04-19 13:46:32 -05:00
Subv
5367935d35 ShaderGen: Fixed a case where the TEXS instruction would use the same registers for the input and the output.
It will now save the coords before writing the outputs in a subscope.
2018-04-19 13:33:17 -05:00
N00byKing
8a47e7e493 Implement Pull #3528 from citra: use nvidia graphics automatically on laptops with optimus (with AMD support) (#271)
* Port 3528: use nvidia graphics automatically on laptops with optimus

* Force dedicated AMD Card for switchable Graphics

* Ran clang-format
2018-04-19 12:22:26 -06:00
James Rowe
e90a12f80c Merge pull request #352 from bunnei/fix-microprofile
nvflinger: Call MicroProfileFlip on NVFlinger::Compose.
2018-04-19 12:18:47 -06:00
bunnei
d019bb16f6 Merge pull request #353 from Subv/compressed_formats
GPU: Add support for the DXT23 and DXT45 compressed texture formats.
2018-04-19 09:02:19 -04:00
Subv
057170928c GPU: Add support for the DXT23 and DXT45 compressed texture formats. 2018-04-18 20:48:53 -05:00
bunnei
de18592179 nvflinger: Call MicroProfileFlip on NVFlinger::Compose. 2018-04-18 20:28:50 -04:00
bunnei
60e6e8953e Merge pull request #351 from Subv/tex_formats
GPU: Implemented the B5G6R5 format.
2018-04-18 20:20:51 -04:00
Subv
2985056340 GPU: Implemented the B5G6R5 format. 2018-04-18 18:16:45 -05:00
bunnei
ce4f159b1c gl_shader_gen: Support vertical/horizontal viewport flipping. (#347)
* gl_shader_gen: Support vertical/horizontal viewport flipping.

* fixup! gl_shader_gen: Support vertical/horizontal viewport flipping.
2018-04-18 16:42:40 -04:00
bunnei
6a999cf800 Merge pull request #350 from Subv/tex_components
GPU: Fixed the incorrect component order in ABGR8 textures.
2018-04-18 15:36:00 -04:00
Subv
43d98ca8fe GLCache: Added boilerplate code to make supporting configurable texture component types.
For now only the UNORM type is supported.
2018-04-18 14:17:28 -05:00
Subv
5b3fab6766 GLCache: Unify texture and framebuffer formats when converting to OpenGL. 2018-04-18 14:17:28 -05:00
Subv
b2c1672e10 GPU: Texture format 8 and framebuffer format 0xD5 are actually ABGR8. 2018-04-18 14:17:27 -05:00
bunnei
d3f9ea90e7 Merge pull request #349 from Subv/texturing
GPU: Support non-tiled textures and configurable block height.
2018-04-18 14:46:10 -04:00
Subv
48d4efbd69 GPU: Pitch textures are now supported, don't assert when encountering them. 2018-04-18 12:52:53 -05:00
Subv
a3e82e8e1f GLCache: Take into account the texture's block height when caching and unswizzling. 2018-04-18 12:52:53 -05:00
Subv
ac09b5a2e9 GLCache: Added a function to convert cached PixelFormats back to texture formats.
TODO: The way we handle cached formats must change, framebuffer and texture formats are too different to keep them in the same place.
2018-04-18 12:52:52 -05:00
Subv
6b63aaa5b4 GPU: Allow using a configurable block height when unswizzling textures. 2018-04-18 12:52:51 -05:00
Subv
db5f2bfa7e GPU/TIC: Added the pitch and block height fields to the TIC structure. 2018-04-18 11:38:39 -05:00
jlachniet
f600f6eebd Technically, yuzu can boot commercial games
Clarifies the yuzu cannot play commercial games to any reasonable extent, rather than not at all.
2018-04-18 09:18:41 -04:00
bunnei
c93ea96366 Merge pull request #346 from bunnei/misc-gpu-improvements
Misc gpu improvements
2018-04-17 22:17:07 -04:00
bunnei
71b4a3b9f6 Merge pull request #344 from bunnei/shader-decompiler-p2
Shader decompiler changes part 2
2018-04-17 22:10:53 -04:00
bunnei
9dc0d13ba5 Merge pull request #345 from bunnei/blending
renderer_opengl: Implement BlendEquation and BlendFunc.
2018-04-17 21:45:36 -04:00
bunnei
7222d9a4c3 gl_rasterizer_cache: Add missing LOG statements. 2018-04-17 21:44:36 -04:00
bunnei
9df8e924fb texture: Add missing formats. 2018-04-17 21:41:36 -04:00
bunnei
3ed8a1cac7 gpu: Add several framebuffer formats to RenderTargetFormat. 2018-04-17 21:40:38 -04:00
bunnei
4a8eb6745e maxwell3d: Allow Texture2DNoMipmap as Texture2D. 2018-04-17 21:39:15 -04:00
bunnei
531c25386e shader_bytecode: Make ctor's constexpr and explicit. 2018-04-17 21:27:07 -04:00
bunnei
174cba5c58 renderer_opengl: Implement BlendEquation and BlendFunc. 2018-04-17 18:11:48 -04:00
bunnei
e59126809c bit_field: Remove is_pod check, add is_trivially_copyable_v. 2018-04-17 18:00:18 -04:00
bunnei
1f6fe062ca gl_shader_decompiler: Fix warnings with MarkAsUsed. 2018-04-17 16:36:44 -04:00
bunnei
ed542a7309 gl_shader_decompiler: Cleanup logging, updating to NGLOG_*. 2018-04-17 16:36:44 -04:00
bunnei
ef2d5ab0c1 gl_shader_decompiler: Implement several MUFU subops and abs_d. 2018-04-17 16:36:43 -04:00
bunnei
59f4ff4659 gl_shader_decompiler: Fix swizzle in GetRegister. 2018-04-17 16:36:42 -04:00
bunnei
5a28dce9eb gl_shader_decompiler: Implement FMUL/FADD/FFMA immediate instructions. 2018-04-17 16:36:42 -04:00
bunnei
8d4899d6ea gl_shader_decompiler: Allow vertex position to be used in fragment shader. 2018-04-17 16:36:40 -04:00
bunnei
95144cc39c gl_shader_decompiler: Implement IPA instruction. 2018-04-17 16:36:39 -04:00
bunnei
8b4443c966 gl_shader_decompiler: Add support for TEXS instruction. 2018-04-17 16:36:38 -04:00
bunnei
5ba71369ac gl_shader_decompiler: Use fragment output color for GPR 0-3. 2018-04-17 15:25:54 -04:00
bunnei
5d529698c9 gl_shader_decompiler: Partially implement MUFU. 2018-04-17 15:25:54 -04:00
bunnei
5b9bcbf438 Merge pull request #341 from shinyquagsire23/pfs-hfs-impl
file_sys: Add HFS/PFS helper component
2018-04-17 14:39:20 -04:00
mailwl
5922f2c46d Service/VI: stub SetLayerVisibility, fix GetDisplayResolution output
both SetLayerVisibility() functions used in Lego games, GetDisplayResolution()
fixed according switchbrew.org
2018-04-17 19:42:14 +03:00
bunnei
2b082e2710 Merge pull request #343 from Subv/tex_wrap_4
GPU: Implement some wrap modes
2018-04-17 12:25:24 -04:00
shinyquagsire23
de580ccdd5 file_sys: Use NGLOG 2018-04-17 09:55:29 -06:00
Hexagon12
e52a87b98a Various service name fixes - part 2 (rebased) (#322)
* Updated ACC with more service names

* Updated SVC with more service names

* Updated set with more service names

* Updated sockets with more service names

* Updated SPL with more service names

* Updated time with more service names

* Updated vi with more service names
2018-04-17 11:37:43 -04:00
bunnei
0905dc1ff4 Merge pull request #342 from bunnei/indexed-verts
Implement indexed mode rendering
2018-04-17 11:34:22 -04:00
Subv
636ad34707 MaxwellToGL: Implemented tex wrap mode 1 (Wrap, GL_REPEAT). 2018-04-17 10:17:18 -05:00
Subv
7fc516cc1a MaxwellToGL: Added a TODO and partial implementation of maxwell wrap mode 4 (Clamp, GL_CLAMP).
This clamp mode was removed from OpenGL as of 3.1, we can emulate it by using GL_CLAMP_TO_BORDER to get the border color of the texture, and then manually sampling the edge to mix them in the fragment shader.
2018-04-17 10:16:50 -05:00
bunnei
77bdc49343 gl_rendering: Use NGLOG* for changed code. 2018-04-16 21:23:28 -04:00
bunnei
1a1af3fda3 gl_rasterizer: Implement indexed vertex mode. 2018-04-16 21:10:15 -04:00
shinyquagsire23
83aa38b239 file_sys: tweaks 2018-04-16 06:51:59 -06:00
shinyquagsire23
c03795300a file_sys: Add HFS/PFS helper component 2018-04-16 04:36:25 -06:00
bunnei
44e09ba807 Merge pull request #338 from bunnei/unrequire-shared-font
pl_u: Use empty shared font if none is available.
2018-04-15 16:54:36 -04:00
bunnei
d6d7d0989c Merge pull request #337 from Subv/used_buffers
GPU: Don't use explicit binding points when uploading the constbuffers to opengl
2018-04-15 16:30:57 -04:00
bunnei
ac628f139d pl_u: Use empty shared font if none is available.
- Makes games work in lieu of shared_font.bin.
2018-04-15 16:15:34 -04:00
Subv
477aab5960 GPU: Use the same buffer names in the generated GLSL and the buffer uploading code. 2018-04-15 15:02:50 -05:00
Subv
14ac40436e GPU: Don't use explicit binding points when uploading the constbuffers to opengl.
The bindpoints will now be dynamically calculated based on the number of buffers used by the previous shader stage.
2018-04-15 14:14:57 -05:00
bunnei
b8825fbf10 Merge pull request #335 from bunnei/delete-file
fsp_srv: Implement DeleteFile.
2018-04-15 15:13:02 -04:00
bunnei
b60834ac41 Merge pull request #334 from Subv/used_buffers
GPU: Use the buffer hints from the shader decompiler to upload only the necessary const buffers for each shader stage
2018-04-15 13:17:30 -04:00
bunnei
bddad50dd4 fsp_srv: Implement DeleteFile.
- Used by Binding of Isaac.
2018-04-15 13:15:18 -04:00
Subv
e128e90350 GPU: Don't use GetPointer when uploading the constbuffer data to the GPU. 2018-04-15 11:18:09 -05:00
Subv
7da47da66e GPU: Use the buffer hints from the shader decompiler to upload only the necessary const buffers for each shader stage. 2018-04-15 11:15:54 -05:00
bunnei
34264879b3 Merge pull request #333 from bunnei/const-buff-hints
shaders: Expose hints about used const buffers.
2018-04-15 12:12:17 -04:00
bunnei
73d9c494ea shaders: Expose hints about used const buffers. 2018-04-15 11:50:10 -04:00
bunnei
bb0c3fc828 Merge pull request #328 from Subv/constbuffers
GPU: Upload the shader Constant Buffers as SSBOs to the GPU
2018-04-15 03:19:57 -04:00
Subv
c9b511da08 GPU: Upload the entirety of each constbuffer for each shader stage as SSBOs.
We're going to need the shader generator to give us a mapping of the actual used const buffers to properly bind them to the shader.
2018-04-14 23:02:05 -05:00
Subv
1957640ea2 GPU: Allow configuring ssbos in the opengl state manager. 2018-04-14 22:54:23 -05:00
Subv
ae58e46036 GPU: Added a function to determine whether a shader stage is enabled or not. 2018-04-14 22:54:23 -05:00
bunnei
2b9a6b3281 Merge pull request #332 from bunnei/fix-total-mem-usage
vm_manager: Increase GetTotalMemoryUsage value.
2018-04-14 22:29:19 -04:00
bunnei
43f0f163e1 vm_manager: Increase GetTotalMemoryUsage value.
- Gets Binding of Isaac running.
2018-04-14 22:04:10 -04:00
bunnei
9f66cae865 Merge pull request #327 from adityaruplaha/fullscreen-fix
Fix the stuck in fullscreen bug
2018-04-14 21:24:36 -04:00
bunnei
778be45103 Merge pull request #331 from bunnei/fsp-flush
fsp_srv: Implement IFile::Flush.
2018-04-14 21:21:34 -04:00
bunnei
fdca7b5f7a Merge pull request #329 from bunnei/shader-gen-part-1
OpenGL shader generation part 1
2018-04-14 20:40:39 -04:00
bunnei
9cab6809f2 fsp_srv: Implement IFile::Flush. 2018-04-14 19:46:09 -04:00
bunnei
1b41b875dc shaders: Add NumTextureSamplers const, remove unused #pragma. 2018-04-14 18:50:06 -04:00
bunnei
e6224fec27 shaders: Address PR review feedback. 2018-04-14 16:01:41 -04:00
bunnei
eabeedf6af gl_shader_decompiler: Cleanup log statements. 2018-04-14 16:01:41 -04:00
bunnei
0d408b965b shaders: Fix GCC and clang build issues. 2018-04-14 16:01:40 -04:00
bunnei
86135864da gl_shader_decompiler: Implement negate, abs, etc. and lots of cleanup. 2018-04-14 16:01:40 -04:00
bunnei
7639667562 shader_bytecode: Add FSETP and KIL to GetInfo. 2018-04-14 16:01:40 -04:00
bunnei
5a47832221 shader_bytecode: Add SubOp decoding. 2018-04-14 16:01:40 -04:00
bunnei
50023bdae7 gl_shader_decompiler: Add shader stage hint. 2018-04-14 16:01:39 -04:00
bunnei
a992aac5eb renderer_opengl: Fix Morton copy byteswap, etc. 2018-04-14 16:01:39 -04:00
adityaruplaha
958c98bdae Fix the stuck in fullscreen bug (Original PR: citra-emu/citra#3611) 2018-04-14 16:41:56 +05:30
bunnei
0ca8fce9d0 gl_shader_manager: Implement SetShaderSamplerBindings. 2018-04-13 23:48:30 -04:00
bunnei
beddc8afd2 gl_rasterizer: Generate shaders and upload uniforms. 2018-04-13 23:48:29 -04:00
bunnei
85d77a3d24 gl_shader_decompiler: Basic impl. for very simple vertex shaders.
- Tested with Puyo Puyo Tetris and Cave Story+
2018-04-13 23:48:28 -04:00
bunnei
51f37f5061 gl_shader_manager: Cleanup and consolidate uniform handling. 2018-04-13 23:48:28 -04:00
bunnei
35aca0bf1f maxwell_3d: Make memory_manager public. 2018-04-13 23:48:27 -04:00
bunnei
33bb53571b maxwell_3d: Fix shader_config decodings. 2018-04-13 23:48:26 -04:00
bunnei
5617831d5f gl_rasterizer: Use shader program manager, remove test shader. 2018-04-13 23:48:26 -04:00
bunnei
459826a705 renderer_opengl: Add gl_shader_manager class. 2018-04-13 23:48:25 -04:00
bunnei
8aa21a03b3 maxwell_to_gl: Add a few types, etc. 2018-04-13 23:48:24 -04:00
bunnei
10953495c1 gl_shader_gen: Add hashable setup/config structs. 2018-04-13 23:48:23 -04:00
bunnei
2fcbb35ad2 gl_shader_util: Add missing includes. 2018-04-13 23:48:23 -04:00
bunnei
45fd7c4a37 common: Port cityhash code from Citra. 2018-04-13 23:48:22 -04:00
bunnei
da1114ca59 renderer_opengl: Use OGLProgram instead of OGLShader. 2018-04-13 23:48:21 -04:00
bunnei
4f2b2d0bc5 gl_shader_util: Grab latest upstream. 2018-04-13 23:48:21 -04:00
bunnei
dbfd106ba0 gl_resource_manager: Grab latest upstream. 2018-04-13 23:48:20 -04:00
bunnei
ed7e597b44 gl_shader_decompiler: Add skeleton code from Citra for shader analysis. 2018-04-13 23:48:20 -04:00
bunnei
4e7e0f8112 shader_bytecode: Add initial module for shader decoding. 2018-04-13 23:48:19 -04:00
bunnei
0315fe8c3d bit_field: Make all methods constexpr. 2018-04-13 23:48:18 -04:00
bunnei
c6ab2c94d9 Merge pull request #323 from Hexagon12/stub-hid
Service/HID: Stubbed out GetPlayerLedPattern
2018-04-13 10:58:03 -04:00
bunnei
660991cffb Merge pull request #325 from Hexagon12/ipc-value-fix
Service/vi: Fix normal_params_size in GetDisplayResolution
2018-04-13 10:57:43 -04:00
Hexagon12
e10248f308 Fixed normal params in GetDisplayResolution 2018-04-13 17:47:01 +03:00
Hexagon12
56d2958aaf Stubbed out GetPlayerLedPattern 2018-04-13 17:05:03 +03:00
Hexagon12
b1556309fe Merge pull request #1 from yuzu-emu/master
Update fork
2018-04-13 15:17:50 +03:00
bunnei
b7369f99ec Merge pull request #319 from Hexagon12/service-name-fix
Various service name fixes - part 1
2018-04-13 00:25:32 -04:00
bunnei
9629736625 Merge pull request #320 from mailwl/ssl-update
Service/SSL: update service according switchbrew
2018-04-11 21:15:18 -04:00
mailwl
39f75350bb Service/SSL: update service according switchbrew 2018-04-11 19:17:18 +03:00
Hexagon12
cc89b7bfcb Various fixes and clang 2018-04-11 14:48:56 +03:00
Hexagon12
a155d3b7ff Decimal change 2018-04-10 21:21:00 +03:00
Hexagon12
88f1fe79c6 Updated pctl:a with new service names. 2018-04-10 21:03:23 +03:00
Hexagon12
177bdb94df Updated nvmemp with new service names. 2018-04-10 20:28:15 +03:00
Hexagon12
4d1a2509df Updated nvdrv with more service names. 2018-04-10 20:26:49 +03:00
Hexagon12
ac50d2cd60 Updated pl:u with more service names. 2018-04-10 20:23:21 +03:00
Hexagon12
2d2de1422e Updated hid with more service names. 2018-04-10 20:17:22 +03:00
Hexagon12
9e2f30ab4a Updated friend:u with more service names. 2018-04-10 20:02:11 +03:00
Hexagon12
be50a6ceef Updated the unknown name 2018-04-10 20:01:33 +03:00
Hexagon12
7788178f01 Updated friend:a with more service names. 2018-04-10 20:00:36 +03:00
bunnei
20c97c60d5 Merge pull request #318 from mailwl/account
Service/ACC: convert to module, add acc:aa, acc:su, acc:u1 services
2018-04-10 12:43:25 -04:00
Hexagon12
ae5e2d07c6 Updated fsp-srv with more service names. 2018-04-10 19:30:27 +03:00
Hexagon12
ee3ca32fa3 Updated CodecCtl with more service names. 2018-04-10 18:58:14 +03:00
Hexagon12
ed2da0ef70 Updated audren with more service names. 2018-04-10 18:56:57 +03:00
Hexagon12
c0011fdacd Updated audrec with more service names. 2018-04-10 18:53:33 +03:00
Hexagon12
a886e3bc2a Updated audout with more service names. 2018-04-10 18:51:50 +03:00
Hexagon12
4cf4a5ecdc Updated audin with more service names. 2018-04-10 18:47:52 +03:00
Hexagon12
c79c9755b4 Updated AOC with more service names. 2018-04-10 18:42:28 +03:00
Hexagon12
434cffa37d Updated AppletOE with more service names. 2018-04-10 18:41:17 +03:00
Hexagon12
0cc2e7d81d Updated AppletAE with more service names. 2018-04-10 18:39:46 +03:00
Hexagon12
84d39530cf Updated AM with more service names. 2018-04-10 18:36:00 +03:00
mailwl
3769a80fac Service/ACC: convert to module, add acc:aa, acc:su, acc:u1 services 2018-04-10 10:18:52 +03:00
227 changed files with 6208 additions and 2975 deletions

View File

@@ -7,7 +7,7 @@ yuzu is an experimental open-source emulator for the Nintendo Switch from the cr
It is written in C++ with portability in mind, with builds actively maintained for Windows, Linux and macOS. The emulator is currently only useful for homebrew development and research purposes.
yuzu only emulates a subset of Switch hardware and therefore is generally only useful for running/debugging homebrew applications. At this time, yuzu does not run any commercial Switch games. yuzu can boot some games, to varying degrees of success, but does not implement any of the necessary GPU features to render 3D graphics.
yuzu only emulates a subset of Switch hardware and therefore is generally only useful for running/debugging homebrew applications. At this time, yuzu cannot play any commercial games without major problems. yuzu can boot some games, to varying degrees of success, but does not implement any of the necessary GPU features to render 3D graphics.
yuzu is licensed under the GPLv2 (or any later version). Refer to the license.txt file included.

View File

@@ -32,14 +32,14 @@ add_library(common STATIC
break_points.cpp
break_points.h
chunk_file.h
code_block.h
cityhash.cpp
cityhash.h
color.h
common_funcs.h
common_paths.h
common_types.h
file_util.cpp
file_util.h
hash.cpp
hash.h
linear_disk_cache.h
logging/backend.cpp

View File

@@ -115,7 +115,7 @@ private:
// assignment would copy the full storage value, rather than just the bits
// relevant to this particular bit field.
// We don't delete it because we want BitField to be trivially copyable.
BitField& operator=(const BitField&) = default;
constexpr BitField& operator=(const BitField&) = default;
// StorageType is T for non-enum types and the underlying type of T if
// T is an enumeration. Note that T is wrapped within an enable_if in the
@@ -166,20 +166,20 @@ public:
// so that we can use this within unions
constexpr BitField() = default;
FORCE_INLINE operator T() const {
constexpr FORCE_INLINE operator T() const {
return Value();
}
FORCE_INLINE void Assign(const T& value) {
constexpr FORCE_INLINE void Assign(const T& value) {
storage = (storage & ~mask) | FormatValue(value);
}
FORCE_INLINE T Value() const {
constexpr T Value() const {
return ExtractValue(storage);
}
// TODO: we may want to change this to explicit operator bool() if it's bug-free in VS2015
FORCE_INLINE bool ToBool() const {
constexpr FORCE_INLINE bool ToBool() const {
return Value() != 0;
}
@@ -192,11 +192,6 @@ private:
static_assert(position < 8 * sizeof(T), "Invalid position");
static_assert(bits <= 8 * sizeof(T), "Invalid number of bits");
static_assert(bits > 0, "Invalid number of bits");
static_assert(std::is_pod<T>::value, "Invalid base type");
static_assert(std::is_trivially_copyable_v<T>, "T must be trivially copyable in a BitField");
};
#pragma pack()
#if (__GNUC__ >= 5) || defined(__clang__) || defined(_MSC_VER)
static_assert(std::is_trivially_copyable<BitField<0, 1, unsigned>>::value,
"BitField must be trivially copyable");
#endif

340
src/common/cityhash.cpp Normal file
View File

@@ -0,0 +1,340 @@
// Copyright (c) 2011 Google, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//
// CityHash, by Geoff Pike and Jyrki Alakuijala
//
// This file provides CityHash64() and related functions.
//
// It's probably possible to create even faster hash functions by
// writing a program that systematically explores some of the space of
// possible hash functions, by using SIMD instructions, or by
// compromising on hash quality.
#include <algorithm>
#include <string.h> // for memcpy and memset
#include "cityhash.h"
#include "common/swap.h"
// #include "config.h"
#ifdef __GNUC__
#define HAVE_BUILTIN_EXPECT 1
#endif
#ifdef COMMON_BIG_ENDIAN
#define WORDS_BIGENDIAN 1
#endif
using namespace std;
typedef uint8_t uint8;
typedef uint32_t uint32;
typedef uint64_t uint64;
namespace Common {
static uint64 UNALIGNED_LOAD64(const char* p) {
uint64 result;
memcpy(&result, p, sizeof(result));
return result;
}
static uint32 UNALIGNED_LOAD32(const char* p) {
uint32 result;
memcpy(&result, p, sizeof(result));
return result;
}
#ifdef WORDS_BIGENDIAN
#define uint32_in_expected_order(x) (swap32(x))
#define uint64_in_expected_order(x) (swap64(x))
#else
#define uint32_in_expected_order(x) (x)
#define uint64_in_expected_order(x) (x)
#endif
#if !defined(LIKELY)
#if HAVE_BUILTIN_EXPECT
#define LIKELY(x) (__builtin_expect(!!(x), 1))
#else
#define LIKELY(x) (x)
#endif
#endif
static uint64 Fetch64(const char* p) {
return uint64_in_expected_order(UNALIGNED_LOAD64(p));
}
static uint32 Fetch32(const char* p) {
return uint32_in_expected_order(UNALIGNED_LOAD32(p));
}
// Some primes between 2^63 and 2^64 for various uses.
static const uint64 k0 = 0xc3a5c85c97cb3127ULL;
static const uint64 k1 = 0xb492b66fbe98f273ULL;
static const uint64 k2 = 0x9ae16a3b2f90404fULL;
// Bitwise right rotate. Normally this will compile to a single
// instruction, especially if the shift is a manifest constant.
static uint64 Rotate(uint64 val, int shift) {
// Avoid shifting by 64: doing so yields an undefined result.
return shift == 0 ? val : ((val >> shift) | (val << (64 - shift)));
}
static uint64 ShiftMix(uint64 val) {
return val ^ (val >> 47);
}
static uint64 HashLen16(uint64 u, uint64 v) {
return Hash128to64(uint128(u, v));
}
static uint64 HashLen16(uint64 u, uint64 v, uint64 mul) {
// Murmur-inspired hashing.
uint64 a = (u ^ v) * mul;
a ^= (a >> 47);
uint64 b = (v ^ a) * mul;
b ^= (b >> 47);
b *= mul;
return b;
}
static uint64 HashLen0to16(const char* s, size_t len) {
if (len >= 8) {
uint64 mul = k2 + len * 2;
uint64 a = Fetch64(s) + k2;
uint64 b = Fetch64(s + len - 8);
uint64 c = Rotate(b, 37) * mul + a;
uint64 d = (Rotate(a, 25) + b) * mul;
return HashLen16(c, d, mul);
}
if (len >= 4) {
uint64 mul = k2 + len * 2;
uint64 a = Fetch32(s);
return HashLen16(len + (a << 3), Fetch32(s + len - 4), mul);
}
if (len > 0) {
uint8 a = s[0];
uint8 b = s[len >> 1];
uint8 c = s[len - 1];
uint32 y = static_cast<uint32>(a) + (static_cast<uint32>(b) << 8);
uint32 z = static_cast<uint32>(len) + (static_cast<uint32>(c) << 2);
return ShiftMix(y * k2 ^ z * k0) * k2;
}
return k2;
}
// This probably works well for 16-byte strings as well, but it may be overkill
// in that case.
static uint64 HashLen17to32(const char* s, size_t len) {
uint64 mul = k2 + len * 2;
uint64 a = Fetch64(s) * k1;
uint64 b = Fetch64(s + 8);
uint64 c = Fetch64(s + len - 8) * mul;
uint64 d = Fetch64(s + len - 16) * k2;
return HashLen16(Rotate(a + b, 43) + Rotate(c, 30) + d, a + Rotate(b + k2, 18) + c, mul);
}
// Return a 16-byte hash for 48 bytes. Quick and dirty.
// Callers do best to use "random-looking" values for a and b.
static pair<uint64, uint64> WeakHashLen32WithSeeds(uint64 w, uint64 x, uint64 y, uint64 z, uint64 a,
uint64 b) {
a += w;
b = Rotate(b + a + z, 21);
uint64 c = a;
a += x;
a += y;
b += Rotate(a, 44);
return make_pair(a + z, b + c);
}
// Return a 16-byte hash for s[0] ... s[31], a, and b. Quick and dirty.
static pair<uint64, uint64> WeakHashLen32WithSeeds(const char* s, uint64 a, uint64 b) {
return WeakHashLen32WithSeeds(Fetch64(s), Fetch64(s + 8), Fetch64(s + 16), Fetch64(s + 24), a,
b);
}
// Return an 8-byte hash for 33 to 64 bytes.
static uint64 HashLen33to64(const char* s, size_t len) {
uint64 mul = k2 + len * 2;
uint64 a = Fetch64(s) * k2;
uint64 b = Fetch64(s + 8);
uint64 c = Fetch64(s + len - 24);
uint64 d = Fetch64(s + len - 32);
uint64 e = Fetch64(s + 16) * k2;
uint64 f = Fetch64(s + 24) * 9;
uint64 g = Fetch64(s + len - 8);
uint64 h = Fetch64(s + len - 16) * mul;
uint64 u = Rotate(a + g, 43) + (Rotate(b, 30) + c) * 9;
uint64 v = ((a + g) ^ d) + f + 1;
uint64 w = swap64((u + v) * mul) + h;
uint64 x = Rotate(e + f, 42) + c;
uint64 y = (swap64((v + w) * mul) + g) * mul;
uint64 z = e + f + c;
a = swap64((x + z) * mul + y) + b;
b = ShiftMix((z + a) * mul + d + h) * mul;
return b + x;
}
uint64 CityHash64(const char* s, size_t len) {
if (len <= 32) {
if (len <= 16) {
return HashLen0to16(s, len);
} else {
return HashLen17to32(s, len);
}
} else if (len <= 64) {
return HashLen33to64(s, len);
}
// For strings over 64 bytes we hash the end first, and then as we
// loop we keep 56 bytes of state: v, w, x, y, and z.
uint64 x = Fetch64(s + len - 40);
uint64 y = Fetch64(s + len - 16) + Fetch64(s + len - 56);
uint64 z = HashLen16(Fetch64(s + len - 48) + len, Fetch64(s + len - 24));
pair<uint64, uint64> v = WeakHashLen32WithSeeds(s + len - 64, len, z);
pair<uint64, uint64> w = WeakHashLen32WithSeeds(s + len - 32, y + k1, x);
x = x * k1 + Fetch64(s);
// Decrease len to the nearest multiple of 64, and operate on 64-byte chunks.
len = (len - 1) & ~static_cast<size_t>(63);
do {
x = Rotate(x + y + v.first + Fetch64(s + 8), 37) * k1;
y = Rotate(y + v.second + Fetch64(s + 48), 42) * k1;
x ^= w.second;
y += v.first + Fetch64(s + 40);
z = Rotate(z + w.first, 33) * k1;
v = WeakHashLen32WithSeeds(s, v.second * k1, x + w.first);
w = WeakHashLen32WithSeeds(s + 32, z + w.second, y + Fetch64(s + 16));
std::swap(z, x);
s += 64;
len -= 64;
} while (len != 0);
return HashLen16(HashLen16(v.first, w.first) + ShiftMix(y) * k1 + z,
HashLen16(v.second, w.second) + x);
}
uint64 CityHash64WithSeed(const char* s, size_t len, uint64 seed) {
return CityHash64WithSeeds(s, len, k2, seed);
}
uint64 CityHash64WithSeeds(const char* s, size_t len, uint64 seed0, uint64 seed1) {
return HashLen16(CityHash64(s, len) - seed0, seed1);
}
// A subroutine for CityHash128(). Returns a decent 128-bit hash for strings
// of any length representable in signed long. Based on City and Murmur.
static uint128 CityMurmur(const char* s, size_t len, uint128 seed) {
uint64 a = Uint128Low64(seed);
uint64 b = Uint128High64(seed);
uint64 c = 0;
uint64 d = 0;
signed long l = static_cast<long>(len) - 16;
if (l <= 0) { // len <= 16
a = ShiftMix(a * k1) * k1;
c = b * k1 + HashLen0to16(s, len);
d = ShiftMix(a + (len >= 8 ? Fetch64(s) : c));
} else { // len > 16
c = HashLen16(Fetch64(s + len - 8) + k1, a);
d = HashLen16(b + len, c + Fetch64(s + len - 16));
a += d;
do {
a ^= ShiftMix(Fetch64(s) * k1) * k1;
a *= k1;
b ^= a;
c ^= ShiftMix(Fetch64(s + 8) * k1) * k1;
c *= k1;
d ^= c;
s += 16;
l -= 16;
} while (l > 0);
}
a = HashLen16(a, c);
b = HashLen16(d, b);
return uint128(a ^ b, HashLen16(b, a));
}
uint128 CityHash128WithSeed(const char* s, size_t len, uint128 seed) {
if (len < 128) {
return CityMurmur(s, len, seed);
}
// We expect len >= 128 to be the common case. Keep 56 bytes of state:
// v, w, x, y, and z.
pair<uint64, uint64> v, w;
uint64 x = Uint128Low64(seed);
uint64 y = Uint128High64(seed);
uint64 z = len * k1;
v.first = Rotate(y ^ k1, 49) * k1 + Fetch64(s);
v.second = Rotate(v.first, 42) * k1 + Fetch64(s + 8);
w.first = Rotate(y + z, 35) * k1 + x;
w.second = Rotate(x + Fetch64(s + 88), 53) * k1;
// This is the same inner loop as CityHash64(), manually unrolled.
do {
x = Rotate(x + y + v.first + Fetch64(s + 8), 37) * k1;
y = Rotate(y + v.second + Fetch64(s + 48), 42) * k1;
x ^= w.second;
y += v.first + Fetch64(s + 40);
z = Rotate(z + w.first, 33) * k1;
v = WeakHashLen32WithSeeds(s, v.second * k1, x + w.first);
w = WeakHashLen32WithSeeds(s + 32, z + w.second, y + Fetch64(s + 16));
std::swap(z, x);
s += 64;
x = Rotate(x + y + v.first + Fetch64(s + 8), 37) * k1;
y = Rotate(y + v.second + Fetch64(s + 48), 42) * k1;
x ^= w.second;
y += v.first + Fetch64(s + 40);
z = Rotate(z + w.first, 33) * k1;
v = WeakHashLen32WithSeeds(s, v.second * k1, x + w.first);
w = WeakHashLen32WithSeeds(s + 32, z + w.second, y + Fetch64(s + 16));
std::swap(z, x);
s += 64;
len -= 128;
} while (LIKELY(len >= 128));
x += Rotate(v.first + z, 49) * k0;
y = y * k0 + Rotate(w.second, 37);
z = z * k0 + Rotate(w.first, 27);
w.first *= 9;
v.first *= k0;
// If 0 < len < 128, hash up to 4 chunks of 32 bytes each from the end of s.
for (size_t tail_done = 0; tail_done < len;) {
tail_done += 32;
y = Rotate(x + y, 42) * k0 + v.second;
w.first += Fetch64(s + len - tail_done + 16);
x = x * k0 + w.first;
z += w.second + Fetch64(s + len - tail_done);
w.second += v.first;
v = WeakHashLen32WithSeeds(s + len - tail_done, v.first + z, v.second);
v.first *= k0;
}
// At this point our 56 bytes of state should contain more than
// enough information for a strong 128-bit hash. We use two
// different 56-byte-to-8-byte hashes to get a 16-byte final result.
x = HashLen16(x, v.first);
y = HashLen16(y + z, w.first);
return uint128(HashLen16(x + v.second, w.second) + y, HashLen16(x + w.second, y + v.second));
}
uint128 CityHash128(const char* s, size_t len) {
return len >= 16
? CityHash128WithSeed(s + 16, len - 16, uint128(Fetch64(s), Fetch64(s + 8) + k0))
: CityHash128WithSeed(s, len, uint128(k0, k1));
}
} // namespace Common

110
src/common/cityhash.h Normal file
View File

@@ -0,0 +1,110 @@
// Copyright (c) 2011 Google, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//
// CityHash, by Geoff Pike and Jyrki Alakuijala
//
// http://code.google.com/p/cityhash/
//
// This file provides a few functions for hashing strings. All of them are
// high-quality functions in the sense that they pass standard tests such
// as Austin Appleby's SMHasher. They are also fast.
//
// For 64-bit x86 code, on short strings, we don't know of anything faster than
// CityHash64 that is of comparable quality. We believe our nearest competitor
// is Murmur3. For 64-bit x86 code, CityHash64 is an excellent choice for hash
// tables and most other hashing (excluding cryptography).
//
// For 64-bit x86 code, on long strings, the picture is more complicated.
// On many recent Intel CPUs, such as Nehalem, Westmere, Sandy Bridge, etc.,
// CityHashCrc128 appears to be faster than all competitors of comparable
// quality. CityHash128 is also good but not quite as fast. We believe our
// nearest competitor is Bob Jenkins' Spooky. We don't have great data for
// other 64-bit CPUs, but for long strings we know that Spooky is slightly
// faster than CityHash on some relatively recent AMD x86-64 CPUs, for example.
// Note that CityHashCrc128 is declared in citycrc.h.
//
// For 32-bit x86 code, we don't know of anything faster than CityHash32 that
// is of comparable quality. We believe our nearest competitor is Murmur3A.
// (On 64-bit CPUs, it is typically faster to use the other CityHash variants.)
//
// Functions in the CityHash family are not suitable for cryptography.
//
// Please see CityHash's README file for more details on our performance
// measurements and so on.
//
// WARNING: This code has been only lightly tested on big-endian platforms!
// It is known to work well on little-endian platforms that have a small penalty
// for unaligned reads, such as current Intel and AMD moderate-to-high-end CPUs.
// It should work on all 32-bit and 64-bit platforms that allow unaligned reads;
// bug reports are welcome.
//
// By the way, for some hash functions, given strings a and b, the hash
// of a+b is easily derived from the hashes of a and b. This property
// doesn't hold for any hash functions in this file.
#pragma once
#include <utility>
#include <stdint.h>
#include <stdlib.h> // for size_t.
namespace Common {
typedef std::pair<uint64_t, uint64_t> uint128;
inline uint64_t Uint128Low64(const uint128& x) {
return x.first;
}
inline uint64_t Uint128High64(const uint128& x) {
return x.second;
}
// Hash function for a byte array.
uint64_t CityHash64(const char* buf, size_t len);
// Hash function for a byte array. For convenience, a 64-bit seed is also
// hashed into the result.
uint64_t CityHash64WithSeed(const char* buf, size_t len, uint64_t seed);
// Hash function for a byte array. For convenience, two seeds are also
// hashed into the result.
uint64_t CityHash64WithSeeds(const char* buf, size_t len, uint64_t seed0, uint64_t seed1);
// Hash function for a byte array.
uint128 CityHash128(const char* s, size_t len);
// Hash function for a byte array. For convenience, a 128-bit seed is also
// hashed into the result.
uint128 CityHash128WithSeed(const char* s, size_t len, uint128 seed);
// Hash 128 input bits down to 64 bits of output.
// This is intended to be a reasonably good hash function.
inline uint64_t Hash128to64(const uint128& x) {
// Murmur-inspired hashing.
const uint64_t kMul = 0x9ddfea08eb382d69ULL;
uint64_t a = (Uint128Low64(x) ^ Uint128High64(x)) * kMul;
a ^= (a >> 47);
uint64_t b = (Uint128High64(x) ^ a) * kMul;
b ^= (b >> 47);
b *= kMul;
return b;
}
} // namespace Common

View File

@@ -1,85 +0,0 @@
// Copyright 2013 Dolphin Emulator Project
// Licensed under GPLv2
// Refer to the license.txt file included.
#pragma once
#include <cstddef>
#include "common/common_types.h"
#include "common/memory_util.h"
// Everything that needs to generate code should inherit from this.
// You get memory management for free, plus, you can use all emitter functions without
// having to prefix them with gen-> or something similar.
// Example implementation:
// class JIT : public CodeBlock<ARMXEmitter> {}
template <class T>
class CodeBlock : public T, NonCopyable {
private:
// A privately used function to set the executable RAM space to something invalid.
// For debugging usefulness it should be used to set the RAM to a host specific breakpoint
// instruction
virtual void PoisonMemory() = 0;
protected:
u8* region;
size_t region_size;
public:
CodeBlock() : region(nullptr), region_size(0) {}
virtual ~CodeBlock() {
if (region)
FreeCodeSpace();
}
// Call this before you generate any code.
void AllocCodeSpace(int size) {
region_size = size;
region = (u8*)AllocateExecutableMemory(region_size);
T::SetCodePtr(region);
}
// Always clear code space with breakpoints, so that if someone accidentally executes
// uninitialized, it just breaks into the debugger.
void ClearCodeSpace() {
PoisonMemory();
ResetCodePtr();
}
// Call this when shutting down. Don't rely on the destructor, even though it'll do the job.
void FreeCodeSpace() {
#ifdef __SYMBIAN32__
ResetExecutableMemory(region);
#else
FreeMemoryPages(region, region_size);
#endif
region = nullptr;
region_size = 0;
}
bool IsInSpace(const u8* ptr) {
return (ptr >= region) && (ptr < (region + region_size));
}
// Cannot currently be undone. Will write protect the entire code region.
// Start over if you need to change the code (call FreeCodeSpace(), AllocCodeSpace()).
void WriteProtect() {
WriteProtectMemory(region, region_size, true);
}
void ResetCodePtr() {
T::SetCodePtr(region);
}
size_t GetSpaceLeft() const {
return region_size - (T::GetCodePtr() - region);
}
u8* GetBasePtr() {
return region;
}
size_t GetOffset(const u8* ptr) const {
return ptr - region;
}
};

View File

@@ -9,8 +9,6 @@
#endif
#include "common/common_types.h"
#define ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0]))
/// Textually concatenates two tokens. The double-expansion is required by the C preprocessor.
#define CONCAT2(x, y) DO_CONCAT2(x, y)
#define DO_CONCAT2(x, y) x##y
@@ -74,11 +72,6 @@ inline u64 _rotr64(u64 x, unsigned int shift) {
#else // _MSC_VER
#if (_MSC_VER < 1900)
// Function Cross-Compatibility
#define snprintf _snprintf
#endif
// Locale Cross-Compatibility
#define locale_t _locale_t

View File

@@ -27,29 +27,23 @@
#include <array>
#include <cstdint>
#ifdef _MSC_VER
#ifndef __func__
#define __func__ __FUNCTION__
#endif
#endif
using u8 = std::uint8_t; ///< 8-bit unsigned byte
using u16 = std::uint16_t; ///< 16-bit unsigned short
using u32 = std::uint32_t; ///< 32-bit unsigned word
using u64 = std::uint64_t; ///< 64-bit unsigned int
typedef std::uint8_t u8; ///< 8-bit unsigned byte
typedef std::uint16_t u16; ///< 16-bit unsigned short
typedef std::uint32_t u32; ///< 32-bit unsigned word
typedef std::uint64_t u64; ///< 64-bit unsigned int
using s8 = std::int8_t; ///< 8-bit signed byte
using s16 = std::int16_t; ///< 16-bit signed short
using s32 = std::int32_t; ///< 32-bit signed word
using s64 = std::int64_t; ///< 64-bit signed int
typedef std::int8_t s8; ///< 8-bit signed byte
typedef std::int16_t s16; ///< 16-bit signed short
typedef std::int32_t s32; ///< 32-bit signed word
typedef std::int64_t s64; ///< 64-bit signed int
typedef float f32; ///< 32-bit floating point
typedef double f64; ///< 64-bit floating point
using f32 = float; ///< 32-bit floating point
using f64 = double; ///< 64-bit floating point
// TODO: It would be nice to eventually replace these with strong types that prevent accidental
// conversion between each other.
typedef u64 VAddr; ///< Represents a pointer in the userspace virtual address space.
typedef u64 PAddr; ///< Represents a pointer in the ARM11 physical address space.
using VAddr = u64; ///< Represents a pointer in the userspace virtual address space.
using PAddr = u64; ///< Represents a pointer in the ARM11 physical address space.
using u128 = std::array<std::uint64_t, 2>;
static_assert(sizeof(u128) == 16, "u128 must be 128 bits wide");

View File

@@ -1,141 +0,0 @@
// Copyright 2015 Citra Emulator Project
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#if defined(_MSC_VER)
#include <stdlib.h>
#endif
#include "common/common_funcs.h"
#include "common/common_types.h"
#include "common/hash.h"
namespace Common {
// MurmurHash3 was written by Austin Appleby, and is placed in the public
// domain. The author hereby disclaims copyright to this source code.
// Block read - if your platform needs to do endian-swapping or can only handle aligned reads, do
// the conversion here
static FORCE_INLINE u64 getblock64(const u64* p, size_t i) {
return p[i];
}
// Finalization mix - force all bits of a hash block to avalanche
static FORCE_INLINE u64 fmix64(u64 k) {
k ^= k >> 33;
k *= 0xff51afd7ed558ccdllu;
k ^= k >> 33;
k *= 0xc4ceb9fe1a85ec53llu;
k ^= k >> 33;
return k;
}
// This is the 128-bit variant of the MurmurHash3 hash function that is targeted for 64-bit
// platforms (MurmurHash3_x64_128). It was taken from:
// https://code.google.com/p/smhasher/source/browse/trunk/MurmurHash3.cpp
void MurmurHash3_128(const void* key, size_t len, u32 seed, void* out) {
const u8* data = (const u8*)key;
const size_t nblocks = len / 16;
u64 h1 = seed;
u64 h2 = seed;
const u64 c1 = 0x87c37b91114253d5llu;
const u64 c2 = 0x4cf5ad432745937fllu;
// Body
const u64* blocks = (const u64*)(data);
for (size_t i = 0; i < nblocks; i++) {
u64 k1 = getblock64(blocks, i * 2 + 0);
u64 k2 = getblock64(blocks, i * 2 + 1);
k1 *= c1;
k1 = _rotl64(k1, 31);
k1 *= c2;
h1 ^= k1;
h1 = _rotl64(h1, 27);
h1 += h2;
h1 = h1 * 5 + 0x52dce729;
k2 *= c2;
k2 = _rotl64(k2, 33);
k2 *= c1;
h2 ^= k2;
h2 = _rotl64(h2, 31);
h2 += h1;
h2 = h2 * 5 + 0x38495ab5;
}
// Tail
const u8* tail = (const u8*)(data + nblocks * 16);
u64 k1 = 0;
u64 k2 = 0;
switch (len & 15) {
case 15:
k2 ^= ((u64)tail[14]) << 48;
case 14:
k2 ^= ((u64)tail[13]) << 40;
case 13:
k2 ^= ((u64)tail[12]) << 32;
case 12:
k2 ^= ((u64)tail[11]) << 24;
case 11:
k2 ^= ((u64)tail[10]) << 16;
case 10:
k2 ^= ((u64)tail[9]) << 8;
case 9:
k2 ^= ((u64)tail[8]) << 0;
k2 *= c2;
k2 = _rotl64(k2, 33);
k2 *= c1;
h2 ^= k2;
case 8:
k1 ^= ((u64)tail[7]) << 56;
case 7:
k1 ^= ((u64)tail[6]) << 48;
case 6:
k1 ^= ((u64)tail[5]) << 40;
case 5:
k1 ^= ((u64)tail[4]) << 32;
case 4:
k1 ^= ((u64)tail[3]) << 24;
case 3:
k1 ^= ((u64)tail[2]) << 16;
case 2:
k1 ^= ((u64)tail[1]) << 8;
case 1:
k1 ^= ((u64)tail[0]) << 0;
k1 *= c1;
k1 = _rotl64(k1, 31);
k1 *= c2;
h1 ^= k1;
};
// Finalization
h1 ^= len;
h2 ^= len;
h1 += h2;
h2 += h1;
h1 = fmix64(h1);
h2 = fmix64(h2);
h1 += h2;
h2 += h1;
((u64*)out)[0] = h1;
((u64*)out)[1] = h2;
}
} // namespace Common

View File

@@ -5,12 +5,12 @@
#pragma once
#include <cstddef>
#include <cstring>
#include "common/cityhash.h"
#include "common/common_types.h"
namespace Common {
void MurmurHash3_128(const void* key, size_t len, u32 seed, void* out);
/**
* Computes a 64-bit hash over the specified block of data
* @param data Block of data to compute hash over
@@ -18,9 +18,54 @@ void MurmurHash3_128(const void* key, size_t len, u32 seed, void* out);
* @returns 64-bit hash value that was computed over the data block
*/
static inline u64 ComputeHash64(const void* data, size_t len) {
u64 res[2];
MurmurHash3_128(data, len, 0, res);
return res[0];
return CityHash64(static_cast<const char*>(data), len);
}
/**
* Computes a 64-bit hash of a struct. In addition to being trivially copyable, it is also critical
* that either the struct includes no padding, or that any padding is initialized to a known value
* by memsetting the struct to 0 before filling it in.
*/
template <typename T>
static inline u64 ComputeStructHash64(const T& data) {
static_assert(std::is_trivially_copyable<T>(),
"Type passed to ComputeStructHash64 must be trivially copyable");
return ComputeHash64(&data, sizeof(data));
}
/// A helper template that ensures the padding in a struct is initialized by memsetting to 0.
template <typename T>
struct HashableStruct {
// In addition to being trivially copyable, T must also have a trivial default constructor,
// because any member initialization would be overridden by memset
static_assert(std::is_trivial<T>(), "Type passed to HashableStruct must be trivial");
/*
* We use a union because "implicitly-defined copy/move constructor for a union X copies the
* object representation of X." and "implicitly-defined copy assignment operator for a union X
* copies the object representation (3.9) of X." = Bytewise copy instead of memberwise copy.
* This is important because the padding bytes are included in the hash and comparison between
* objects.
*/
union {
T state;
};
HashableStruct() {
// Memset structure to zero padding bits, so that they will be deterministic when hashing
std::memset(&state, 0, sizeof(T));
}
bool operator==(const HashableStruct<T>& o) const {
return std::memcmp(&state, &o.state, sizeof(T)) == 0;
};
bool operator!=(const HashableStruct<T>& o) const {
return !(*this == o);
};
size_t Hash() const {
return Common::ComputeStructHash64(state);
}
};
} // namespace Common

View File

@@ -17,11 +17,6 @@ inline bool IntervalsIntersect(unsigned start0, unsigned length0, unsigned start
return (std::max(start0, start1) < std::min(start0 + length0, start1 + length1));
}
template <typename T>
inline T Clamp(const T val, const T& min, const T& max) {
return std::max(min, std::min(max, val));
}
template <class T>
struct Rectangle {
T left;

View File

@@ -11,25 +11,6 @@
#include <thread>
#include "common/common_types.h"
// Support for C++11's thread_local keyword was surprisingly spotty in compilers until very
// recently. Fortunately, thread local variables have been well supported for compilers for a while,
// but with semantics supporting only POD types, so we can use a few defines to get some amount of
// backwards compat support.
// WARNING: This only works correctly with POD types.
#if defined(__clang__)
#if !__has_feature(cxx_thread_local)
#define thread_local __thread
#endif
#elif defined(__GNUC__)
#if __GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 8)
#define thread_local __thread
#endif
#elif defined(_MSC_VER)
#if _MSC_VER < 1900
#define thread_local __declspec(thread)
#endif
#endif
namespace Common {
int CurrentThreadId();

View File

@@ -55,10 +55,6 @@ public:
T x;
T y;
T* AsArray() {
return &x;
}
Vec2() = default;
Vec2(const T& _x, const T& _y) : x(_x), y(_y) {}
@@ -71,11 +67,6 @@ public:
return Vec2<T>(f, f);
}
void Write(T a[2]) {
a[0] = x;
a[1] = y;
}
Vec2<decltype(T{} + T{})> operator+(const Vec2& other) const {
return MakeVec(x + other.x, y + other.y);
}
@@ -205,10 +196,6 @@ public:
T y;
T z;
T* AsArray() {
return &x;
}
Vec3() = default;
Vec3(const T& _x, const T& _y, const T& _z) : x(_x), y(_y), z(_z) {}
@@ -225,12 +212,6 @@ public:
return MakeVec(f, f, f);
}
void Write(T a[3]) {
a[0] = x;
a[1] = y;
a[2] = z;
}
Vec3<decltype(T{} + T{})> operator+(const Vec3& other) const {
return MakeVec(x + other.x, y + other.y, z + other.z);
}
@@ -416,10 +397,6 @@ public:
T z;
T w;
T* AsArray() {
return &x;
}
Vec4() = default;
Vec4(const T& _x, const T& _y, const T& _z, const T& _w) : x(_x), y(_y), z(_z), w(_w) {}
@@ -436,13 +413,6 @@ public:
return Vec4<T>(f, f, f, f);
}
void Write(T a[4]) {
a[0] = x;
a[1] = y;
a[2] = z;
a[3] = w;
}
Vec4<decltype(T{} + T{})> operator+(const Vec4& other) const {
return MakeVec(x + other.x, y + other.y, z + other.z, w + other.w);
}

View File

@@ -12,6 +12,8 @@ add_library(core STATIC
file_sys/errors.h
file_sys/filesystem.cpp
file_sys/filesystem.h
file_sys/partition_filesystem.cpp
file_sys/partition_filesystem.h
file_sys/path_parser.cpp
file_sys/path_parser.h
file_sys/program_metadata.cpp
@@ -40,8 +42,6 @@ add_library(core STATIC
hle/kernel/client_port.h
hle/kernel/client_session.cpp
hle/kernel/client_session.h
hle/kernel/condition_variable.cpp
hle/kernel/condition_variable.h
hle/kernel/errors.h
hle/kernel/event.cpp
hle/kernel/event.h
@@ -88,8 +88,14 @@ add_library(core STATIC
hle/romfs.h
hle/service/acc/acc.cpp
hle/service/acc/acc.h
hle/service/acc/acc_aa.cpp
hle/service/acc/acc_aa.h
hle/service/acc/acc_su.cpp
hle/service/acc/acc_su.h
hle/service/acc/acc_u0.cpp
hle/service/acc/acc_u0.h
hle/service/acc/acc_u1.cpp
hle/service/acc/acc_u1.h
hle/service/am/am.cpp
hle/service/am/am.h
hle/service/am/applet_ae.cpp

View File

@@ -12,10 +12,13 @@
#include "core/core.h"
#include "core/core_timing.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/thread.h"
#include "core/hle/service/service.h"
#include "core/hle/service/sm/controller.h"
#include "core/hle/service/sm/sm.h"
#include "core/hw/hw.h"
#include "core/loader/loader.h"
#include "core/memory_setup.h"
@@ -26,6 +29,8 @@ namespace Core {
/*static*/ System System::s_instance;
System::~System() = default;
System::ResultStatus System::RunLoop(bool tight_loop) {
status = ResultStatus::Success;
if (!cpu_core) {
@@ -167,10 +172,12 @@ System::ResultStatus System::Init(EmuWindow* emu_window, u32 system_mode) {
telemetry_session = std::make_unique<Core::TelemetrySession>();
service_manager = std::make_shared<Service::SM::ServiceManager>();
HW::Init();
Kernel::Init(system_mode);
scheduler = std::make_unique<Kernel::Scheduler>(cpu_core.get());
Service::Init();
Service::Init(service_manager);
GDBStub::Init();
if (!VideoCore::Init(emu_window)) {
@@ -200,17 +207,26 @@ void System::Shutdown() {
VideoCore::Shutdown();
GDBStub::Shutdown();
Service::Shutdown();
scheduler = nullptr;
scheduler.reset();
Kernel::Shutdown();
HW::Shutdown();
telemetry_session = nullptr;
gpu_core = nullptr;
cpu_core = nullptr;
service_manager.reset();
telemetry_session.reset();
gpu_core.reset();
cpu_core.reset();
CoreTiming::Shutdown();
app_loader = nullptr;
app_loader.reset();
LOG_DEBUG(Core, "Shutdown OK");
}
Service::SM::ServiceManager& System::ServiceManager() {
return *service_manager;
}
const Service::SM::ServiceManager& System::ServiceManager() const {
return *service_manager;
}
} // namespace Core

View File

@@ -19,10 +19,16 @@
class EmuWindow;
class ARM_Interface;
namespace Service::SM {
class ServiceManager;
}
namespace Core {
class System {
public:
~System();
/**
* Gets the instance of the System singleton class.
* @returns Reference to the instance of the System singleton class.
@@ -137,6 +143,9 @@ public:
return *app_loader;
}
Service::SM::ServiceManager& ServiceManager();
const Service::SM::ServiceManager& ServiceManager() const;
void SetGPUDebugContext(std::shared_ptr<Tegra::DebugContext> context) {
debug_context = std::move(context);
}
@@ -171,6 +180,9 @@ private:
/// When true, signals that a reschedule should happen
bool reschedule_pending{};
/// Service manager
std::shared_ptr<Service::SM::ServiceManager> service_manager;
/// Telemetry session for this emulation session
std::unique_ptr<Core::TelemetrySession> telemetry_session;

View File

@@ -57,16 +57,26 @@ ResultVal<std::unique_ptr<StorageBackend>> Disk_FileSystem::OpenFile(const std::
std::make_unique<Disk_Storage>(std::move(file)));
}
ResultCode Disk_FileSystem::DeleteFile(const Path& path) const {
LOG_WARNING(Service_FS, "(STUBBED) called");
// TODO(bunnei): Use correct error code
return ResultCode(-1);
ResultCode Disk_FileSystem::DeleteFile(const std::string& path) const {
if (!FileUtil::Exists(path)) {
return ERROR_PATH_NOT_FOUND;
}
FileUtil::Delete(path);
return RESULT_SUCCESS;
}
ResultCode Disk_FileSystem::RenameFile(const Path& src_path, const Path& dest_path) const {
LOG_WARNING(Service_FS, "(STUBBED) called");
ResultCode Disk_FileSystem::RenameFile(const std::string& src_path,
const std::string& dest_path) const {
const std::string full_src_path = base_directory + src_path;
const std::string full_dest_path = base_directory + dest_path;
if (!FileUtil::Exists(full_src_path)) {
return ERROR_PATH_NOT_FOUND;
}
// TODO(wwylele): Use correct error code
return ResultCode(-1);
return FileUtil::Rename(full_src_path, full_dest_path) ? RESULT_SUCCESS : ResultCode(-1);
}
ResultCode Disk_FileSystem::DeleteDirectory(const Path& path) const {
@@ -179,7 +189,7 @@ bool Disk_Storage::SetSize(const u64 size) const {
return true;
}
Disk_Directory::Disk_Directory(const std::string& path) : directory() {
Disk_Directory::Disk_Directory(const std::string& path) {
unsigned size = FileUtil::ScanDirectoryTree(path, directory);
directory.size = size;
directory.isDirectory = true;

View File

@@ -25,8 +25,8 @@ public:
ResultVal<std::unique_ptr<StorageBackend>> OpenFile(const std::string& path,
Mode mode) const override;
ResultCode DeleteFile(const Path& path) const override;
ResultCode RenameFile(const Path& src_path, const Path& dest_path) const override;
ResultCode DeleteFile(const std::string& path) const override;
ResultCode RenameFile(const std::string& src_path, const std::string& dest_path) const override;
ResultCode DeleteDirectory(const Path& path) const override;
ResultCode DeleteDirectoryRecursively(const Path& path) const override;
ResultCode CreateFile(const std::string& path, u64 size) const override;
@@ -43,7 +43,7 @@ protected:
class Disk_Storage : public StorageBackend {
public:
Disk_Storage(std::shared_ptr<FileUtil::IOFile> file) : file(std::move(file)) {}
explicit Disk_Storage(std::shared_ptr<FileUtil::IOFile> file) : file(std::move(file)) {}
ResultVal<size_t> Read(u64 offset, size_t length, u8* buffer) const override;
ResultVal<size_t> Write(u64 offset, size_t length, bool flush, const u8* buffer) const override;
@@ -60,7 +60,7 @@ private:
class Disk_Directory : public DirectoryBackend {
public:
Disk_Directory(const std::string& path);
explicit Disk_Directory(const std::string& path);
~Disk_Directory() override {
Close();
@@ -74,7 +74,6 @@ public:
}
protected:
u32 total_entries_in_directory;
FileUtil::FSTEntry directory;
// We need to remember the last entry we returned, so a subsequent call to Read will continue

View File

@@ -97,7 +97,7 @@ public:
* @param path Path relative to the archive
* @return Result of the operation
*/
virtual ResultCode DeleteFile(const Path& path) const = 0;
virtual ResultCode DeleteFile(const std::string& path) const = 0;
/**
* Create a directory specified by its path
@@ -126,7 +126,8 @@ public:
* @param dest_path Destination path relative to the archive
* @return Result of the operation
*/
virtual ResultCode RenameFile(const Path& src_path, const Path& dest_path) const = 0;
virtual ResultCode RenameFile(const std::string& src_path,
const std::string& dest_path) const = 0;
/**
* Rename a Directory specified by its path

View File

@@ -0,0 +1,125 @@
// Copyright 2018 yuzu emulator team
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#include <cinttypes>
#include <utility>
#include "common/file_util.h"
#include "common/logging/log.h"
#include "core/file_sys/partition_filesystem.h"
#include "core/loader/loader.h"
namespace FileSys {
Loader::ResultStatus PartitionFilesystem::Load(const std::string& file_path, size_t offset) {
FileUtil::IOFile file(file_path, "rb");
if (!file.IsOpen())
return Loader::ResultStatus::Error;
// At least be as large as the header
if (file.GetSize() < sizeof(Header))
return Loader::ResultStatus::Error;
// For cartridges, HFSs can get very large, so we need to calculate the size up to
// the actual content itself instead of just blindly reading in the entire file.
Header pfs_header;
if (!file.ReadBytes(&pfs_header, sizeof(Header)))
return Loader::ResultStatus::Error;
bool is_hfs = (memcmp(pfs_header.magic.data(), "HFS", 3) == 0);
size_t entry_size = is_hfs ? sizeof(HFSEntry) : sizeof(PFSEntry);
size_t metadata_size =
sizeof(Header) + (pfs_header.num_entries * entry_size) + pfs_header.strtab_size;
// Actually read in now...
file.Seek(offset, SEEK_SET);
std::vector<u8> file_data(metadata_size);
if (!file.ReadBytes(file_data.data(), metadata_size))
return Loader::ResultStatus::Error;
Loader::ResultStatus result = Load(file_data);
if (result != Loader::ResultStatus::Success)
LOG_ERROR(Service_FS, "Failed to load PFS from file %s!", file_path.c_str());
return result;
}
Loader::ResultStatus PartitionFilesystem::Load(const std::vector<u8>& file_data, size_t offset) {
size_t total_size = file_data.size() - offset;
if (total_size < sizeof(Header))
return Loader::ResultStatus::Error;
memcpy(&pfs_header, &file_data[offset], sizeof(Header));
is_hfs = (memcmp(pfs_header.magic.data(), "HFS", 3) == 0);
size_t entries_offset = offset + sizeof(Header);
size_t entry_size = is_hfs ? sizeof(HFSEntry) : sizeof(PFSEntry);
size_t strtab_offset = entries_offset + (pfs_header.num_entries * entry_size);
for (u16 i = 0; i < pfs_header.num_entries; i++) {
FileEntry entry;
memcpy(&entry.fs_entry, &file_data[entries_offset + (i * entry_size)], sizeof(FSEntry));
entry.name = std::string(reinterpret_cast<const char*>(
&file_data[strtab_offset + entry.fs_entry.strtab_offset]));
pfs_entries.push_back(std::move(entry));
}
content_offset = strtab_offset + pfs_header.strtab_size;
return Loader::ResultStatus::Success;
}
u32 PartitionFilesystem::GetNumEntries() const {
return pfs_header.num_entries;
}
u64 PartitionFilesystem::GetEntryOffset(int index) const {
if (index > GetNumEntries())
return 0;
return content_offset + pfs_entries[index].fs_entry.offset;
}
u64 PartitionFilesystem::GetEntrySize(int index) const {
if (index > GetNumEntries())
return 0;
return pfs_entries[index].fs_entry.size;
}
std::string PartitionFilesystem::GetEntryName(int index) const {
if (index > GetNumEntries())
return "";
return pfs_entries[index].name;
}
u64 PartitionFilesystem::GetFileOffset(const std::string& name) const {
for (u32 i = 0; i < pfs_header.num_entries; i++) {
if (pfs_entries[i].name == name)
return content_offset + pfs_entries[i].fs_entry.offset;
}
return 0;
}
u64 PartitionFilesystem::GetFileSize(const std::string& name) const {
for (u32 i = 0; i < pfs_header.num_entries; i++) {
if (pfs_entries[i].name == name)
return pfs_entries[i].fs_entry.size;
}
return 0;
}
void PartitionFilesystem::Print() const {
NGLOG_DEBUG(Service_FS, "Magic: {:.4}", pfs_header.magic.data());
NGLOG_DEBUG(Service_FS, "Files: {}", pfs_header.num_entries);
for (u32 i = 0; i < pfs_header.num_entries; i++) {
NGLOG_DEBUG(Service_FS, " > File {}: {} (0x{:X} bytes, at 0x{:X})", i,
pfs_entries[i].name.c_str(), pfs_entries[i].fs_entry.size,
GetFileOffset(pfs_entries[i].name));
}
}
} // namespace FileSys

View File

@@ -0,0 +1,87 @@
// Copyright 2018 yuzu emulator team
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#pragma once
#include <array>
#include <string>
#include <vector>
#include "common/common_funcs.h"
#include "common/common_types.h"
#include "common/swap.h"
namespace Loader {
enum class ResultStatus;
}
namespace FileSys {
/**
* Helper which implements an interface to parse PFS/HFS filesystems.
* Data can either be loaded from a file path or data with an offset into it.
*/
class PartitionFilesystem {
public:
Loader::ResultStatus Load(const std::string& file_path, size_t offset = 0);
Loader::ResultStatus Load(const std::vector<u8>& file_data, size_t offset = 0);
u32 GetNumEntries() const;
u64 GetEntryOffset(int index) const;
u64 GetEntrySize(int index) const;
std::string GetEntryName(int index) const;
u64 GetFileOffset(const std::string& name) const;
u64 GetFileSize(const std::string& name) const;
void Print() const;
private:
struct Header {
std::array<char, 4> magic;
u32_le num_entries;
u32_le strtab_size;
INSERT_PADDING_BYTES(0x4);
};
static_assert(sizeof(Header) == 0x10, "PFS/HFS header structure size is wrong");
#pragma pack(push, 1)
struct FSEntry {
u64_le offset;
u64_le size;
u32_le strtab_offset;
};
static_assert(sizeof(FSEntry) == 0x14, "FS entry structure size is wrong");
struct PFSEntry {
FSEntry fs_entry;
INSERT_PADDING_BYTES(0x4);
};
static_assert(sizeof(PFSEntry) == 0x18, "PFS entry structure size is wrong");
struct HFSEntry {
FSEntry fs_entry;
u32_le hash_region_size;
INSERT_PADDING_BYTES(0x8);
std::array<char, 0x20> hash;
};
static_assert(sizeof(HFSEntry) == 0x40, "HFS entry structure size is wrong");
#pragma pack(pop)
struct FileEntry {
FSEntry fs_entry;
std::string name;
};
Header pfs_header;
bool is_hfs;
size_t content_offset;
std::vector<FileEntry> pfs_entries;
};
} // namespace FileSys

View File

@@ -20,14 +20,15 @@ ResultVal<std::unique_ptr<StorageBackend>> RomFS_FileSystem::OpenFile(const std:
std::make_unique<RomFS_Storage>(romfs_file, data_offset, data_size));
}
ResultCode RomFS_FileSystem::DeleteFile(const Path& path) const {
ResultCode RomFS_FileSystem::DeleteFile(const std::string& path) const {
LOG_CRITICAL(Service_FS, "Attempted to delete a file from an ROMFS archive (%s).",
GetName().c_str());
// TODO(bunnei): Use correct error code
return ResultCode(-1);
}
ResultCode RomFS_FileSystem::RenameFile(const Path& src_path, const Path& dest_path) const {
ResultCode RomFS_FileSystem::RenameFile(const std::string& src_path,
const std::string& dest_path) const {
LOG_CRITICAL(Service_FS, "Attempted to rename a file within an ROMFS archive (%s).",
GetName().c_str());
// TODO(wwylele): Use correct error code

View File

@@ -31,8 +31,8 @@ public:
ResultVal<std::unique_ptr<StorageBackend>> OpenFile(const std::string& path,
Mode mode) const override;
ResultCode DeleteFile(const Path& path) const override;
ResultCode RenameFile(const Path& src_path, const Path& dest_path) const override;
ResultCode DeleteFile(const std::string& path) const override;
ResultCode RenameFile(const std::string& src_path, const std::string& dest_path) const override;
ResultCode DeleteDirectory(const Path& path) const override;
ResultCode DeleteDirectoryRecursively(const Path& path) const override;
ResultCode CreateFile(const std::string& path, u64 size) const override;

View File

@@ -1,64 +0,0 @@
// Copyright 2018 yuzu emulator team
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#include "common/assert.h"
#include "core/hle/kernel/condition_variable.h"
#include "core/hle/kernel/errors.h"
#include "core/hle/kernel/kernel.h"
#include "core/hle/kernel/object_address_table.h"
#include "core/hle/kernel/thread.h"
namespace Kernel {
ConditionVariable::ConditionVariable() {}
ConditionVariable::~ConditionVariable() {}
ResultVal<SharedPtr<ConditionVariable>> ConditionVariable::Create(VAddr guest_addr,
std::string name) {
SharedPtr<ConditionVariable> condition_variable(new ConditionVariable);
condition_variable->name = std::move(name);
condition_variable->guest_addr = guest_addr;
condition_variable->mutex_addr = 0;
// Condition variables are referenced by guest address, so track this in the kernel
g_object_address_table.Insert(guest_addr, condition_variable);
return MakeResult<SharedPtr<ConditionVariable>>(std::move(condition_variable));
}
bool ConditionVariable::ShouldWait(Thread* thread) const {
return GetAvailableCount() <= 0;
}
void ConditionVariable::Acquire(Thread* thread) {
if (GetAvailableCount() <= 0)
return;
SetAvailableCount(GetAvailableCount() - 1);
}
ResultCode ConditionVariable::Release(s32 target) {
if (target == -1) {
// When -1, wake up all waiting threads
SetAvailableCount(static_cast<s32>(GetWaitingThreads().size()));
WakeupAllWaitingThreads();
} else {
// Otherwise, wake up just a single thread
SetAvailableCount(target);
WakeupWaitingThread(GetHighestPriorityReadyThread());
}
return RESULT_SUCCESS;
}
s32 ConditionVariable::GetAvailableCount() const {
return Memory::Read32(guest_addr);
}
void ConditionVariable::SetAvailableCount(s32 value) const {
Memory::Write32(guest_addr, value);
}
} // namespace Kernel

View File

@@ -1,63 +0,0 @@
// Copyright 2018 yuzu emulator team
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#pragma once
#include <string>
#include <queue>
#include "common/common_types.h"
#include "core/hle/kernel/kernel.h"
#include "core/hle/kernel/wait_object.h"
#include "core/hle/result.h"
namespace Kernel {
class ConditionVariable final : public WaitObject {
public:
/**
* Creates a condition variable.
* @param guest_addr Address of the object tracking the condition variable in guest memory. If
* specified, this condition variable will update the guest object when its state changes.
* @param name Optional name of condition variable.
* @return The created condition variable.
*/
static ResultVal<SharedPtr<ConditionVariable>> Create(VAddr guest_addr,
std::string name = "Unknown");
std::string GetTypeName() const override {
return "ConditionVariable";
}
std::string GetName() const override {
return name;
}
static const HandleType HANDLE_TYPE = HandleType::ConditionVariable;
HandleType GetHandleType() const override {
return HANDLE_TYPE;
}
s32 GetAvailableCount() const;
void SetAvailableCount(s32 value) const;
std::string name; ///< Name of condition variable (optional)
VAddr guest_addr; ///< Address of the guest condition variable value
VAddr mutex_addr; ///< (optional) Address of guest mutex value associated with this condition
///< variable, used for implementing events
bool ShouldWait(Thread* thread) const override;
void Acquire(Thread* thread) override;
/**
* Releases a slot from a condition variable.
* @param target The number of threads to wakeup, -1 is all.
* @return ResultCode indicating if the operation succeeded.
*/
ResultCode Release(s32 target);
private:
ConditionVariable();
~ConditionVariable() override;
};
} // namespace Kernel

View File

@@ -20,6 +20,7 @@ enum {
MaxConnectionsReached = 52,
// Confirmed Switch OS error codes
MisalignedAddress = 102,
InvalidHandle = 114,
Timeout = 117,
SynchronizationCanceled = 118,

View File

@@ -18,12 +18,10 @@ using Handle = u32;
enum class HandleType : u32 {
Unknown,
Event,
Mutex,
SharedMemory,
Thread,
Process,
AddressArbiter,
ConditionVariable,
Timer,
ResourceLimit,
CodeSet,
@@ -63,9 +61,7 @@ public:
bool IsWaitable() const {
switch (GetHandleType()) {
case HandleType::Event:
case HandleType::Mutex:
case HandleType::Thread:
case HandleType::ConditionVariable:
case HandleType::Timer:
case HandleType::ServerPort:
case HandleType::ServerSession:

View File

@@ -7,6 +7,7 @@
#include <boost/range/algorithm_ext/erase.hpp>
#include "common/assert.h"
#include "core/core.h"
#include "core/hle/kernel/errors.h"
#include "core/hle/kernel/handle_table.h"
#include "core/hle/kernel/kernel.h"
#include "core/hle/kernel/mutex.h"
@@ -15,124 +16,120 @@
namespace Kernel {
void ReleaseThreadMutexes(Thread* thread) {
for (auto& mtx : thread->held_mutexes) {
mtx->SetHasWaiters(false);
mtx->SetHoldingThread(nullptr);
mtx->WakeupAllWaitingThreads();
}
thread->held_mutexes.clear();
}
/// Returns the number of threads that are waiting for a mutex, and the highest priority one among
/// those.
static std::pair<SharedPtr<Thread>, u32> GetHighestPriorityMutexWaitingThread(
SharedPtr<Thread> current_thread, VAddr mutex_addr) {
Mutex::Mutex() {}
Mutex::~Mutex() {}
SharedPtr<Thread> highest_priority_thread;
u32 num_waiters = 0;
SharedPtr<Mutex> Mutex::Create(SharedPtr<Kernel::Thread> holding_thread, VAddr guest_addr,
std::string name) {
SharedPtr<Mutex> mutex(new Mutex);
for (auto& thread : current_thread->wait_mutex_threads) {
if (thread->mutex_wait_address != mutex_addr)
continue;
mutex->guest_addr = guest_addr;
mutex->name = std::move(name);
ASSERT(thread->status == THREADSTATUS_WAIT_MUTEX);
// If mutex was initialized with a holding thread, acquire it by the holding thread
if (holding_thread) {
mutex->Acquire(holding_thread.get());
++num_waiters;
if (highest_priority_thread == nullptr ||
thread->GetPriority() < highest_priority_thread->GetPriority()) {
highest_priority_thread = thread;
}
}
// Mutexes are referenced by guest address, so track this in the kernel
g_object_address_table.Insert(guest_addr, mutex);
return mutex;
return {highest_priority_thread, num_waiters};
}
bool Mutex::ShouldWait(Thread* thread) const {
auto holding_thread = GetHoldingThread();
return holding_thread != nullptr && thread != holding_thread;
/// Update the mutex owner field of all threads waiting on the mutex to point to the new owner.
static void TransferMutexOwnership(VAddr mutex_addr, SharedPtr<Thread> current_thread,
SharedPtr<Thread> new_owner) {
auto threads = current_thread->wait_mutex_threads;
for (auto& thread : threads) {
if (thread->mutex_wait_address != mutex_addr)
continue;
ASSERT(thread->lock_owner == current_thread);
current_thread->RemoveMutexWaiter(thread);
if (new_owner != thread)
new_owner->AddMutexWaiter(thread);
}
}
void Mutex::Acquire(Thread* thread) {
ASSERT_MSG(!ShouldWait(thread), "object unavailable!");
ResultCode Mutex::TryAcquire(VAddr address, Handle holding_thread_handle,
Handle requesting_thread_handle) {
// The mutex address must be 4-byte aligned
if ((address % sizeof(u32)) != 0) {
return ResultCode(ErrorModule::Kernel, ErrCodes::MisalignedAddress);
}
priority = thread->current_priority;
thread->held_mutexes.insert(this);
SetHoldingThread(thread);
thread->UpdatePriority();
Core::System::GetInstance().PrepareReschedule();
}
SharedPtr<Thread> holding_thread = g_handle_table.Get<Thread>(holding_thread_handle);
SharedPtr<Thread> requesting_thread = g_handle_table.Get<Thread>(requesting_thread_handle);
ResultCode Mutex::Release(Thread* thread) {
auto holding_thread = GetHoldingThread();
ASSERT(holding_thread);
// TODO(Subv): It is currently unknown if it is possible to lock a mutex in behalf of another
// thread.
ASSERT(requesting_thread == GetCurrentThread());
// We can only release the mutex if it's held by the calling thread.
ASSERT(thread == holding_thread);
u32 addr_value = Memory::Read32(address);
// If the mutex isn't being held, just return success.
if (addr_value != (holding_thread_handle | Mutex::MutexHasWaitersFlag)) {
return RESULT_SUCCESS;
}
if (holding_thread == nullptr)
return ERR_INVALID_HANDLE;
// Wait until the mutex is released
GetCurrentThread()->mutex_wait_address = address;
GetCurrentThread()->wait_handle = requesting_thread_handle;
GetCurrentThread()->status = THREADSTATUS_WAIT_MUTEX;
GetCurrentThread()->wakeup_callback = nullptr;
// Update the lock holder thread's priority to prevent priority inversion.
holding_thread->AddMutexWaiter(GetCurrentThread());
holding_thread->held_mutexes.erase(this);
holding_thread->UpdatePriority();
SetHoldingThread(nullptr);
SetHasWaiters(!GetWaitingThreads().empty());
WakeupAllWaitingThreads();
Core::System::GetInstance().PrepareReschedule();
return RESULT_SUCCESS;
}
void Mutex::AddWaitingThread(SharedPtr<Thread> thread) {
WaitObject::AddWaitingThread(thread);
thread->pending_mutexes.insert(this);
SetHasWaiters(true);
UpdatePriority();
}
void Mutex::RemoveWaitingThread(Thread* thread) {
WaitObject::RemoveWaitingThread(thread);
thread->pending_mutexes.erase(this);
if (!GetHasWaiters())
SetHasWaiters(!GetWaitingThreads().empty());
UpdatePriority();
}
void Mutex::UpdatePriority() {
if (!GetHoldingThread())
return;
u32 best_priority = THREADPRIO_LOWEST;
for (auto& waiter : GetWaitingThreads()) {
if (waiter->current_priority < best_priority)
best_priority = waiter->current_priority;
ResultCode Mutex::Release(VAddr address) {
// The mutex address must be 4-byte aligned
if ((address % sizeof(u32)) != 0) {
return ResultCode(ErrorModule::Kernel, ErrCodes::MisalignedAddress);
}
if (best_priority != priority) {
priority = best_priority;
GetHoldingThread()->UpdatePriority();
auto [thread, num_waiters] = GetHighestPriorityMutexWaitingThread(GetCurrentThread(), address);
// There are no more threads waiting for the mutex, release it completely.
if (thread == nullptr) {
ASSERT(GetCurrentThread()->wait_mutex_threads.empty());
Memory::Write32(address, 0);
return RESULT_SUCCESS;
}
}
Handle Mutex::GetOwnerHandle() const {
GuestState guest_state{Memory::Read32(guest_addr)};
return guest_state.holding_thread_handle;
}
// Transfer the ownership of the mutex from the previous owner to the new one.
TransferMutexOwnership(address, GetCurrentThread(), thread);
SharedPtr<Thread> Mutex::GetHoldingThread() const {
GuestState guest_state{Memory::Read32(guest_addr)};
return g_handle_table.Get<Thread>(guest_state.holding_thread_handle);
}
u32 mutex_value = thread->wait_handle;
void Mutex::SetHoldingThread(SharedPtr<Thread> thread) {
GuestState guest_state{Memory::Read32(guest_addr)};
guest_state.holding_thread_handle.Assign(thread ? thread->guest_handle : 0);
Memory::Write32(guest_addr, guest_state.raw);
}
if (num_waiters >= 2) {
// Notify the guest that there are still some threads waiting for the mutex
mutex_value |= Mutex::MutexHasWaitersFlag;
}
bool Mutex::GetHasWaiters() const {
GuestState guest_state{Memory::Read32(guest_addr)};
return guest_state.has_waiters != 0;
}
// Grant the mutex to the next waiting thread and resume it.
Memory::Write32(address, mutex_value);
void Mutex::SetHasWaiters(bool has_waiters) {
GuestState guest_state{Memory::Read32(guest_addr)};
guest_state.has_waiters.Assign(has_waiters ? 1 : 0);
Memory::Write32(guest_addr, guest_state.raw);
}
ASSERT(thread->status == THREADSTATUS_WAIT_MUTEX);
thread->ResumeFromWait();
thread->lock_owner = nullptr;
thread->condvar_wait_address = 0;
thread->mutex_wait_address = 0;
thread->wait_handle = 0;
return RESULT_SUCCESS;
}
} // namespace Kernel

View File

@@ -15,87 +15,23 @@ namespace Kernel {
class Thread;
class Mutex final : public WaitObject {
class Mutex final {
public:
/**
* Creates a mutex.
* @param holding_thread Specifies a thread already holding the mutex. If not nullptr, this
* thread will acquire the mutex.
* @param guest_addr Address of the object tracking the mutex in guest memory. If specified,
* this mutex will update the guest object when its state changes.
* @param name Optional name of mutex
* @return Pointer to new Mutex object
*/
static SharedPtr<Mutex> Create(SharedPtr<Kernel::Thread> holding_thread, VAddr guest_addr = 0,
std::string name = "Unknown");
/// Flag that indicates that a mutex still has threads waiting for it.
static constexpr u32 MutexHasWaitersFlag = 0x40000000;
/// Mask of the bits in a mutex address value that contain the mutex owner.
static constexpr u32 MutexOwnerMask = 0xBFFFFFFF;
std::string GetTypeName() const override {
return "Mutex";
}
std::string GetName() const override {
return name;
}
/// Attempts to acquire a mutex at the specified address.
static ResultCode TryAcquire(VAddr address, Handle holding_thread_handle,
Handle requesting_thread_handle);
static const HandleType HANDLE_TYPE = HandleType::Mutex;
HandleType GetHandleType() const override {
return HANDLE_TYPE;
}
u32 priority; ///< The priority of the mutex, used for priority inheritance.
std::string name; ///< Name of mutex (optional)
VAddr guest_addr; ///< Address of the guest mutex value
/**
* Elevate the mutex priority to the best priority
* among the priorities of all its waiting threads.
*/
void UpdatePriority();
bool ShouldWait(Thread* thread) const override;
void Acquire(Thread* thread) override;
void AddWaitingThread(SharedPtr<Thread> thread) override;
void RemoveWaitingThread(Thread* thread) override;
/**
* Attempts to release the mutex from the specified thread.
* @param thread Thread that wants to release the mutex.
* @returns The result code of the operation.
*/
ResultCode Release(Thread* thread);
/// Gets the handle to the holding process stored in the guest state.
Handle GetOwnerHandle() const;
/// Gets the Thread pointed to by the owner handle
SharedPtr<Thread> GetHoldingThread() const;
/// Sets the holding process handle in the guest state.
void SetHoldingThread(SharedPtr<Thread> thread);
/// Returns the has_waiters bit in the guest state.
bool GetHasWaiters() const;
/// Sets the has_waiters bit in the guest state.
void SetHasWaiters(bool has_waiters);
/// Releases the mutex at the specified address.
static ResultCode Release(VAddr address);
private:
Mutex();
~Mutex() override;
/// Object in guest memory used to track the mutex state
union GuestState {
u32_le raw;
/// Handle of the thread that currently holds the mutex, 0 if available
BitField<0, 30, u32_le> holding_thread_handle;
/// 1 when there are threads waiting for this mutex, otherwise 0
BitField<30, 1, u32_le> has_waiters;
};
static_assert(sizeof(GuestState) == 4, "GuestState size is incorrect");
Mutex() = default;
~Mutex() = default;
};
/**
* Releases all the mutexes held by the specified thread
* @param thread Thread that is holding the mutexes
*/
void ReleaseThreadMutexes(Thread* thread);
} // namespace Kernel

View File

@@ -34,57 +34,57 @@ SharedPtr<ResourceLimit> ResourceLimit::GetForCategory(ResourceLimitCategory cat
}
}
s32 ResourceLimit::GetCurrentResourceValue(u32 resource) const {
s32 ResourceLimit::GetCurrentResourceValue(ResourceType resource) const {
switch (resource) {
case COMMIT:
case ResourceType::Commit:
return current_commit;
case THREAD:
case ResourceType::Thread:
return current_threads;
case EVENT:
case ResourceType::Event:
return current_events;
case MUTEX:
case ResourceType::Mutex:
return current_mutexes;
case SEMAPHORE:
case ResourceType::Semaphore:
return current_semaphores;
case TIMER:
case ResourceType::Timer:
return current_timers;
case SHARED_MEMORY:
case ResourceType::SharedMemory:
return current_shared_mems;
case ADDRESS_ARBITER:
case ResourceType::AddressArbiter:
return current_address_arbiters;
case CPU_TIME:
case ResourceType::CPUTime:
return current_cpu_time;
default:
LOG_ERROR(Kernel, "Unknown resource type=%08X", resource);
LOG_ERROR(Kernel, "Unknown resource type=%08X", static_cast<u32>(resource));
UNIMPLEMENTED();
return 0;
}
}
u32 ResourceLimit::GetMaxResourceValue(u32 resource) const {
u32 ResourceLimit::GetMaxResourceValue(ResourceType resource) const {
switch (resource) {
case PRIORITY:
case ResourceType::Priority:
return max_priority;
case COMMIT:
case ResourceType::Commit:
return max_commit;
case THREAD:
case ResourceType::Thread:
return max_threads;
case EVENT:
case ResourceType::Event:
return max_events;
case MUTEX:
case ResourceType::Mutex:
return max_mutexes;
case SEMAPHORE:
case ResourceType::Semaphore:
return max_semaphores;
case TIMER:
case ResourceType::Timer:
return max_timers;
case SHARED_MEMORY:
case ResourceType::SharedMemory:
return max_shared_mems;
case ADDRESS_ARBITER:
case ResourceType::AddressArbiter:
return max_address_arbiters;
case CPU_TIME:
case ResourceType::CPUTime:
return max_cpu_time;
default:
LOG_ERROR(Kernel, "Unknown resource type=%08X", resource);
LOG_ERROR(Kernel, "Unknown resource type=%08X", static_cast<u32>(resource));
UNIMPLEMENTED();
return 0;
}

View File

@@ -16,17 +16,17 @@ enum class ResourceLimitCategory : u8 {
OTHER = 3
};
enum ResourceTypes {
PRIORITY = 0,
COMMIT = 1,
THREAD = 2,
EVENT = 3,
MUTEX = 4,
SEMAPHORE = 5,
TIMER = 6,
SHARED_MEMORY = 7,
ADDRESS_ARBITER = 8,
CPU_TIME = 9,
enum class ResourceType {
Priority = 0,
Commit = 1,
Thread = 2,
Event = 3,
Mutex = 4,
Semaphore = 5,
Timer = 6,
SharedMemory = 7,
AddressArbiter = 8,
CPUTime = 9,
};
class ResourceLimit final : public Object {
@@ -60,14 +60,14 @@ public:
* @param resource Requested resource type
* @returns The current value of the resource type
*/
s32 GetCurrentResourceValue(u32 resource) const;
s32 GetCurrentResourceValue(ResourceType resource) const;
/**
* Gets the max value for the specified resource.
* @param resource Requested resource type
* @returns The max value of the resource type
*/
u32 GetMaxResourceValue(u32 resource) const;
u32 GetMaxResourceValue(ResourceType resource) const;
/// Name of resource limit object.
std::string name;

View File

@@ -4,6 +4,7 @@
#include <algorithm>
#include <cinttypes>
#include <iterator>
#include "common/logging/log.h"
#include "common/microprofile.h"
@@ -12,7 +13,6 @@
#include "core/core_timing.h"
#include "core/hle/kernel/client_port.h"
#include "core/hle/kernel/client_session.h"
#include "core/hle/kernel/condition_variable.h"
#include "core/hle/kernel/event.h"
#include "core/hle/kernel/handle_table.h"
#include "core/hle/kernel/mutex.h"
@@ -261,32 +261,14 @@ static ResultCode ArbitrateLock(Handle holding_thread_handle, VAddr mutex_addr,
"requesting_current_thread_handle=0x%08X",
holding_thread_handle, mutex_addr, requesting_thread_handle);
SharedPtr<Thread> holding_thread = g_handle_table.Get<Thread>(holding_thread_handle);
SharedPtr<Thread> requesting_thread = g_handle_table.Get<Thread>(requesting_thread_handle);
ASSERT(requesting_thread);
ASSERT(requesting_thread == GetCurrentThread());
SharedPtr<Mutex> mutex = g_object_address_table.Get<Mutex>(mutex_addr);
if (!mutex) {
// Create a new mutex for the specified address if one does not already exist
mutex = Mutex::Create(holding_thread, mutex_addr);
mutex->name = Common::StringFromFormat("mutex-%llx", mutex_addr);
}
ASSERT(holding_thread == mutex->GetHoldingThread());
return WaitSynchronization1(mutex, requesting_thread.get());
return Mutex::TryAcquire(mutex_addr, holding_thread_handle, requesting_thread_handle);
}
/// Unlock a mutex
static ResultCode ArbitrateUnlock(VAddr mutex_addr) {
LOG_TRACE(Kernel_SVC, "called mutex_addr=0x%llx", mutex_addr);
SharedPtr<Mutex> mutex = g_object_address_table.Get<Mutex>(mutex_addr);
ASSERT(mutex);
return mutex->Release(GetCurrentThread());
return Mutex::Release(mutex_addr);
}
/// Break program execution
@@ -406,16 +388,11 @@ static ResultCode SetThreadPriority(Handle handle, u32 priority) {
// Note: The kernel uses the current process's resource limit instead of
// the one from the thread owner's resource limit.
SharedPtr<ResourceLimit>& resource_limit = Core::CurrentProcess()->resource_limit;
if (resource_limit->GetMaxResourceValue(ResourceTypes::PRIORITY) > priority) {
if (resource_limit->GetMaxResourceValue(ResourceType::Priority) > priority) {
return ERR_NOT_AUTHORIZED;
}
thread->SetPriority(priority);
thread->UpdatePriority();
// Update the mutexes that this thread is waiting for
for (auto& mutex : thread->pending_mutexes)
mutex->UpdatePriority();
Core::System::GetInstance().PrepareReschedule();
return RESULT_SUCCESS;
@@ -540,7 +517,7 @@ static ResultCode CreateThread(Handle* out_handle, VAddr entry_point, u64 arg, V
}
SharedPtr<ResourceLimit>& resource_limit = Core::CurrentProcess()->resource_limit;
if (resource_limit->GetMaxResourceValue(ResourceTypes::PRIORITY) > priority) {
if (resource_limit->GetMaxResourceValue(ResourceType::Priority) > priority) {
return ERR_NOT_AUTHORIZED;
}
@@ -633,77 +610,20 @@ static ResultCode WaitProcessWideKeyAtomic(VAddr mutex_addr, VAddr condition_var
SharedPtr<Thread> thread = g_handle_table.Get<Thread>(thread_handle);
ASSERT(thread);
SharedPtr<Mutex> mutex = g_object_address_table.Get<Mutex>(mutex_addr);
if (!mutex) {
// Create a new mutex for the specified address if one does not already exist
mutex = Mutex::Create(thread, mutex_addr);
mutex->name = Common::StringFromFormat("mutex-%llx", mutex_addr);
}
CASCADE_CODE(Mutex::Release(mutex_addr));
SharedPtr<ConditionVariable> condition_variable =
g_object_address_table.Get<ConditionVariable>(condition_variable_addr);
if (!condition_variable) {
// Create a new condition_variable for the specified address if one does not already exist
condition_variable = ConditionVariable::Create(condition_variable_addr).Unwrap();
condition_variable->name =
Common::StringFromFormat("condition-variable-%llx", condition_variable_addr);
}
SharedPtr<Thread> current_thread = GetCurrentThread();
current_thread->condvar_wait_address = condition_variable_addr;
current_thread->mutex_wait_address = mutex_addr;
current_thread->wait_handle = thread_handle;
current_thread->status = THREADSTATUS_WAIT_MUTEX;
current_thread->wakeup_callback = nullptr;
if (condition_variable->mutex_addr) {
// Previously created the ConditionVariable using WaitProcessWideKeyAtomic, verify
// everything is correct
ASSERT(condition_variable->mutex_addr == mutex_addr);
} else {
// Previously created the ConditionVariable using SignalProcessWideKey, set the mutex
// associated with it
condition_variable->mutex_addr = mutex_addr;
}
current_thread->WakeAfterDelay(nano_seconds);
if (mutex->GetOwnerHandle()) {
// Release the mutex if the current thread is holding it
mutex->Release(thread.get());
}
auto wakeup_callback = [mutex, nano_seconds](ThreadWakeupReason reason,
SharedPtr<Thread> thread,
SharedPtr<WaitObject> object, size_t index) {
ASSERT(thread->status == THREADSTATUS_WAIT_SYNCH_ANY);
if (reason == ThreadWakeupReason::Timeout) {
thread->SetWaitSynchronizationResult(RESULT_TIMEOUT);
return true;
}
ASSERT(reason == ThreadWakeupReason::Signal);
// Now try to acquire the mutex and don't resume if it's not available.
if (!mutex->ShouldWait(thread.get())) {
mutex->Acquire(thread.get());
thread->SetWaitSynchronizationResult(RESULT_SUCCESS);
return true;
}
if (nano_seconds == 0) {
thread->SetWaitSynchronizationResult(RESULT_TIMEOUT);
return true;
}
thread->wait_objects = {mutex};
mutex->AddWaitingThread(thread);
thread->status = THREADSTATUS_WAIT_SYNCH_ANY;
// Create an event to wake the thread up after the
// specified nanosecond delay has passed
thread->WakeAfterDelay(nano_seconds);
thread->wakeup_callback = DefaultThreadWakeupCallback;
Core::System::GetInstance().PrepareReschedule();
return false;
};
CASCADE_CODE(
WaitSynchronization1(condition_variable, thread.get(), nano_seconds, wakeup_callback));
// Note: Deliberately don't attempt to inherit the lock owner's priority.
Core::System::GetInstance().PrepareReschedule();
return RESULT_SUCCESS;
}
@@ -712,24 +632,53 @@ static ResultCode SignalProcessWideKey(VAddr condition_variable_addr, s32 target
LOG_TRACE(Kernel_SVC, "called, condition_variable_addr=0x%llx, target=0x%08x",
condition_variable_addr, target);
// Wakeup all or one thread - Any other value is unimplemented
ASSERT(target == -1 || target == 1);
u32 processed = 0;
auto& thread_list = Core::System::GetInstance().Scheduler().GetThreadList();
SharedPtr<ConditionVariable> condition_variable =
g_object_address_table.Get<ConditionVariable>(condition_variable_addr);
if (!condition_variable) {
// Create a new condition_variable for the specified address if one does not already exist
condition_variable = ConditionVariable::Create(condition_variable_addr).Unwrap();
condition_variable->name =
Common::StringFromFormat("condition-variable-%llx", condition_variable_addr);
}
for (auto& thread : thread_list) {
if (thread->condvar_wait_address != condition_variable_addr)
continue;
CASCADE_CODE(condition_variable->Release(target));
// Only process up to 'target' threads, unless 'target' is -1, in which case process
// them all.
if (target != -1 && processed >= target)
break;
if (condition_variable->mutex_addr) {
// If a mutex was created for this condition_variable, wait the current thread on it
SharedPtr<Mutex> mutex = g_object_address_table.Get<Mutex>(condition_variable->mutex_addr);
return WaitSynchronization1(mutex, GetCurrentThread());
// If the mutex is not yet acquired, acquire it.
u32 mutex_val = Memory::Read32(thread->mutex_wait_address);
if (mutex_val == 0) {
// We were able to acquire the mutex, resume this thread.
Memory::Write32(thread->mutex_wait_address, thread->wait_handle);
ASSERT(thread->status == THREADSTATUS_WAIT_MUTEX);
thread->ResumeFromWait();
auto lock_owner = thread->lock_owner;
if (lock_owner)
lock_owner->RemoveMutexWaiter(thread);
thread->lock_owner = nullptr;
thread->mutex_wait_address = 0;
thread->condvar_wait_address = 0;
thread->wait_handle = 0;
} else {
// Couldn't acquire the mutex, block the thread.
Handle owner_handle = static_cast<Handle>(mutex_val & Mutex::MutexOwnerMask);
auto owner = g_handle_table.Get<Thread>(owner_handle);
ASSERT(owner);
ASSERT(thread->status != THREADSTATUS_RUNNING);
thread->status = THREADSTATUS_WAIT_MUTEX;
thread->wakeup_callback = nullptr;
// Signal that the mutex now has a waiting thread.
Memory::Write32(thread->mutex_wait_address, mutex_val | Mutex::MutexHasWaitersFlag);
owner->AddMutexWaiter(thread);
Core::System::GetInstance().PrepareReschedule();
}
++processed;
}
return RESULT_SUCCESS;
@@ -861,14 +810,14 @@ static const FunctionDef SVC_Table[] = {
{0x2B, nullptr, "FlushDataCache"},
{0x2C, nullptr, "MapPhysicalMemory"},
{0x2D, nullptr, "UnmapPhysicalMemory"},
{0x2E, nullptr, "Unknown"},
{0x2E, nullptr, "GetNextThreadInfo"},
{0x2F, nullptr, "GetLastThreadInfo"},
{0x30, nullptr, "GetResourceLimitLimitValue"},
{0x31, nullptr, "GetResourceLimitCurrentValue"},
{0x32, SvcWrap<SetThreadActivity>, "SetThreadActivity"},
{0x33, SvcWrap<GetThreadContext>, "GetThreadContext"},
{0x34, nullptr, "Unknown"},
{0x35, nullptr, "Unknown"},
{0x34, nullptr, "WaitForAddress"},
{0x35, nullptr, "SignalToAddress"},
{0x36, nullptr, "Unknown"},
{0x37, nullptr, "Unknown"},
{0x38, nullptr, "Unknown"},
@@ -876,7 +825,7 @@ static const FunctionDef SVC_Table[] = {
{0x3A, nullptr, "Unknown"},
{0x3B, nullptr, "Unknown"},
{0x3C, nullptr, "DumpInfo"},
{0x3D, nullptr, "Unknown"},
{0x3D, nullptr, "DumpInfoNew"},
{0x3E, nullptr, "Unknown"},
{0x3F, nullptr, "Unknown"},
{0x40, nullptr, "CreateSession"},
@@ -887,9 +836,9 @@ static const FunctionDef SVC_Table[] = {
{0x45, nullptr, "CreateEvent"},
{0x46, nullptr, "Unknown"},
{0x47, nullptr, "Unknown"},
{0x48, nullptr, "Unknown"},
{0x49, nullptr, "Unknown"},
{0x4A, nullptr, "Unknown"},
{0x48, nullptr, "AllocateUnsafeMemory"},
{0x49, nullptr, "FreeUnsafeMemory"},
{0x4A, nullptr, "SetUnsafeAllocationLimit"},
{0x4B, nullptr, "CreateJitMemory"},
{0x4C, nullptr, "MapJitMemory"},
{0x4D, nullptr, "SleepSystem"},
@@ -926,7 +875,7 @@ static const FunctionDef SVC_Table[] = {
{0x6C, nullptr, "SetHardwareBreakPoint"},
{0x6D, nullptr, "GetDebugThreadParam"},
{0x6E, nullptr, "Unknown"},
{0x6F, nullptr, "Unknown"},
{0x6F, nullptr, "GetMemoryInfo"},
{0x70, nullptr, "CreatePort"},
{0x71, nullptr, "ManageNamedPort"},
{0x72, nullptr, "ConnectToPort"},
@@ -946,7 +895,7 @@ static const FunctionDef SVC_Table[] = {
};
static const FunctionDef* GetSVCInfo(u32 func_num) {
if (func_num >= ARRAY_SIZE(SVC_Table)) {
if (func_num >= std::size(SVC_Table)) {
LOG_ERROR(Kernel_SVC, "unknown svc=0x%02X", func_num);
return nullptr;
}

View File

@@ -77,9 +77,6 @@ void Thread::Stop() {
}
wait_objects.clear();
// Release all the mutexes that this thread holds
ReleaseThreadMutexes(this);
// Mark the TLS slot in the thread's page as free.
u64 tls_page = (tls_address - Memory::TLS_AREA_VADDR) / Memory::PAGE_SIZE;
u64 tls_slot =
@@ -126,6 +123,19 @@ static void ThreadWakeupCallback(u64 thread_handle, int cycles_late) {
resume = thread->wakeup_callback(ThreadWakeupReason::Timeout, thread, nullptr, 0);
}
if (thread->mutex_wait_address != 0 || thread->condvar_wait_address != 0 ||
thread->wait_handle) {
ASSERT(thread->status == THREADSTATUS_WAIT_MUTEX);
thread->mutex_wait_address = 0;
thread->condvar_wait_address = 0;
thread->wait_handle = 0;
auto lock_owner = thread->lock_owner;
// Threads waking up by timeout from WaitProcessWideKey do not perform priority inheritance
// and don't have a lock owner.
ASSERT(lock_owner == nullptr);
}
if (resume)
thread->ResumeFromWait();
}
@@ -151,6 +161,7 @@ void Thread::ResumeFromWait() {
case THREADSTATUS_WAIT_HLE_EVENT:
case THREADSTATUS_WAIT_SLEEP:
case THREADSTATUS_WAIT_IPC:
case THREADSTATUS_WAIT_MUTEX:
break;
case THREADSTATUS_READY:
@@ -256,7 +267,9 @@ ResultVal<SharedPtr<Thread>> Thread::Create(std::string name, VAddr entry_point,
thread->last_running_ticks = CoreTiming::GetTicks();
thread->processor_id = processor_id;
thread->wait_objects.clear();
thread->wait_address = 0;
thread->mutex_wait_address = 0;
thread->condvar_wait_address = 0;
thread->wait_handle = 0;
thread->name = std::move(name);
thread->callback_handle = wakeup_callback_handle_table.Create(thread).Unwrap();
thread->owner_process = owner_process;
@@ -317,17 +330,8 @@ ResultVal<SharedPtr<Thread>> Thread::Create(std::string name, VAddr entry_point,
void Thread::SetPriority(u32 priority) {
ASSERT_MSG(priority <= THREADPRIO_LOWEST && priority >= THREADPRIO_HIGHEST,
"Invalid priority value.");
Core::System::GetInstance().Scheduler().SetThreadPriority(this, priority);
nominal_priority = current_priority = priority;
}
void Thread::UpdatePriority() {
u32 best_priority = nominal_priority;
for (auto& mutex : held_mutexes) {
if (mutex->priority < best_priority)
best_priority = mutex->priority;
}
BoostPriority(best_priority);
nominal_priority = priority;
UpdatePriority();
}
void Thread::BoostPriority(u32 priority) {
@@ -377,6 +381,38 @@ VAddr Thread::GetCommandBufferAddress() const {
return GetTLSAddress() + CommandHeaderOffset;
}
void Thread::AddMutexWaiter(SharedPtr<Thread> thread) {
thread->lock_owner = this;
wait_mutex_threads.emplace_back(std::move(thread));
UpdatePriority();
}
void Thread::RemoveMutexWaiter(SharedPtr<Thread> thread) {
boost::remove_erase(wait_mutex_threads, thread);
thread->lock_owner = nullptr;
UpdatePriority();
}
void Thread::UpdatePriority() {
// Find the highest priority among all the threads that are waiting for this thread's lock
u32 new_priority = nominal_priority;
for (const auto& thread : wait_mutex_threads) {
if (thread->nominal_priority < new_priority)
new_priority = thread->nominal_priority;
}
if (new_priority == current_priority)
return;
Core::System::GetInstance().Scheduler().SetThreadPriority(this, new_priority);
current_priority = new_priority;
// Recursively update the priority of the thread that depends on the priority of this one.
if (lock_owner)
lock_owner->UpdatePriority();
}
////////////////////////////////////////////////////////////////////////////////////////////////////
/**

View File

@@ -18,7 +18,7 @@
enum ThreadPriority : u32 {
THREADPRIO_HIGHEST = 0, ///< Highest thread priority
THREADPRIO_USERLAND_MAX = 24, ///< Highest thread priority for userland apps
THREADPRIO_DEFAULT = 48, ///< Default thread priority for userland apps
THREADPRIO_DEFAULT = 44, ///< Default thread priority for userland apps
THREADPRIO_LOWEST = 63, ///< Lowest thread priority
};
@@ -43,6 +43,7 @@ enum ThreadStatus {
THREADSTATUS_WAIT_IPC, ///< Waiting for the reply from an IPC request
THREADSTATUS_WAIT_SYNCH_ANY, ///< Waiting due to WaitSynch1 or WaitSynchN with wait_all = false
THREADSTATUS_WAIT_SYNCH_ALL, ///< Waiting due to WaitSynchronizationN with wait_all = true
THREADSTATUS_WAIT_MUTEX, ///< Waiting due to an ArbitrateLock/WaitProcessWideKey svc
THREADSTATUS_DORMANT, ///< Created but not yet made ready
THREADSTATUS_DEAD ///< Run to completion, or forcefully terminated
};
@@ -54,7 +55,6 @@ enum class ThreadWakeupReason {
namespace Kernel {
class Mutex;
class Process;
class Thread final : public WaitObject {
@@ -103,18 +103,21 @@ public:
*/
void SetPriority(u32 priority);
/**
* Boost's a thread's priority to the best priority among the thread's held mutexes.
* This prevents priority inversion via priority inheritance.
*/
void UpdatePriority();
/**
* 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);
/// Removes a thread from the list of threads that are waiting for a lock held by this thread.
void RemoveMutexWaiter(SharedPtr<Thread> thread);
/// Recalculates the current priority taking into account priority inheritance.
void UpdatePriority();
/**
* Gets the thread's thread ID
* @return The thread's ID
@@ -205,19 +208,22 @@ public:
VAddr tls_address; ///< Virtual address of the Thread Local Storage of the thread
/// Mutexes currently held by this thread, which will be released when it exits.
boost::container::flat_set<SharedPtr<Mutex>> held_mutexes;
/// Mutexes that this thread is currently waiting for.
boost::container::flat_set<SharedPtr<Mutex>> pending_mutexes;
SharedPtr<Process> owner_process; ///< Process that owns this thread
/// Objects that the thread is waiting on, in the same order as they were
// passed to WaitSynchronization1/N.
std::vector<SharedPtr<WaitObject>> wait_objects;
VAddr wait_address; ///< If waiting on an AddressArbiter, this is the arbitration address
/// List of threads that are waiting for a mutex that is held by this thread.
std::vector<SharedPtr<Thread>> wait_mutex_threads;
/// Thread that owns the lock that this thread is waiting for.
SharedPtr<Thread> lock_owner;
// If waiting on a ConditionVariable, this is the ConditionVariable address
VAddr condvar_wait_address;
VAddr mutex_wait_address; ///< If waiting on a Mutex, this is the mutex address
Handle wait_handle; ///< The handle used to wait for the mutex.
std::string name;

View File

@@ -380,7 +380,7 @@ void VMManager::UpdatePageTableForVMA(const VirtualMemoryArea& vma) {
u64 VMManager::GetTotalMemoryUsage() {
LOG_WARNING(Kernel, "(STUBBED) called");
return 0xBE000000;
return 0xF8000000;
}
u64 VMManager::GetTotalHeapUsage() {

View File

@@ -2,15 +2,149 @@
// 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/acc/acc.h"
#include "core/hle/service/acc/acc_aa.h"
#include "core/hle/service/acc/acc_su.h"
#include "core/hle/service/acc/acc_u0.h"
#include "core/hle/service/acc/acc_u1.h"
namespace Service {
namespace Account {
namespace Service::Account {
void InstallInterfaces(SM::ServiceManager& service_manager) {
std::make_shared<ACC_U0>()->InstallAsService(service_manager);
// TODO: RE this structure
struct UserData {
INSERT_PADDING_WORDS(1);
u32 icon_id;
u8 bg_color_id;
INSERT_PADDING_BYTES(0x7);
INSERT_PADDING_BYTES(0x10);
INSERT_PADDING_BYTES(0x60);
};
static_assert(sizeof(UserData) == 0x80, "UserData structure has incorrect size");
struct ProfileBase {
u8 user_id[0x10];
u64 timestamp;
u8 username[0x20];
};
static_assert(sizeof(ProfileBase) == 0x38, "ProfileBase structure has incorrect size");
using Uid = std::array<u64, 2>;
static constexpr Uid DEFAULT_USER_ID{0x10ull, 0x20ull};
class IProfile final : public ServiceFramework<IProfile> {
public:
IProfile() : ServiceFramework("IProfile") {
static const FunctionInfo functions[] = {
{0, nullptr, "Get"},
{1, &IProfile::GetBase, "GetBase"},
{10, nullptr, "GetImageSize"},
{11, nullptr, "LoadImage"},
};
RegisterHandlers(functions);
}
private:
void GetBase(Kernel::HLERequestContext& ctx) {
NGLOG_WARNING(Service_ACC, "(STUBBED) called");
ProfileBase profile_base{};
IPC::ResponseBuilder rb{ctx, 16};
rb.Push(RESULT_SUCCESS);
rb.PushRaw(profile_base);
}
};
class IManagerForApplication final : public ServiceFramework<IManagerForApplication> {
public:
IManagerForApplication() : ServiceFramework("IManagerForApplication") {
static const FunctionInfo functions[] = {
{0, &IManagerForApplication::CheckAvailability, "CheckAvailability"},
{1, &IManagerForApplication::GetAccountId, "GetAccountId"},
{2, nullptr, "EnsureIdTokenCacheAsync"},
{3, nullptr, "LoadIdTokenCache"},
{130, nullptr, "GetNintendoAccountUserResourceCacheForApplication"},
{150, nullptr, "CreateAuthorizationRequest"},
{160, nullptr, "StoreOpenContext"},
};
RegisterHandlers(functions);
}
private:
void CheckAvailability(Kernel::HLERequestContext& ctx) {
NGLOG_WARNING(Service_ACC, "(STUBBED) called");
IPC::ResponseBuilder rb{ctx, 3};
rb.Push(RESULT_SUCCESS);
rb.Push(true); // TODO: Check when this is supposed to return true and when not
}
void GetAccountId(Kernel::HLERequestContext& ctx) {
NGLOG_WARNING(Service_ACC, "(STUBBED) called");
IPC::ResponseBuilder rb{ctx, 4};
rb.Push(RESULT_SUCCESS);
rb.Push<u64>(0x12345678ABCDEF);
}
};
void Module::Interface::GetUserExistence(Kernel::HLERequestContext& ctx) {
NGLOG_WARNING(Service_ACC, "(STUBBED) called");
IPC::ResponseBuilder rb{ctx, 3};
rb.Push(RESULT_SUCCESS);
rb.Push(true); // TODO: Check when this is supposed to return true and when not
}
} // namespace Account
} // namespace Service
void Module::Interface::ListAllUsers(Kernel::HLERequestContext& ctx) {
NGLOG_WARNING(Service_ACC, "(STUBBED) called");
constexpr std::array<u128, 10> user_ids{DEFAULT_USER_ID};
ctx.WriteBuffer(user_ids.data(), user_ids.size());
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS);
}
void Module::Interface::ListOpenUsers(Kernel::HLERequestContext& ctx) {
NGLOG_WARNING(Service_ACC, "(STUBBED) called");
constexpr std::array<u128, 10> user_ids{DEFAULT_USER_ID};
ctx.WriteBuffer(user_ids.data(), user_ids.size());
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS);
}
void Module::Interface::GetProfile(Kernel::HLERequestContext& ctx) {
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(RESULT_SUCCESS);
rb.PushIpcInterface<IProfile>();
NGLOG_DEBUG(Service_ACC, "called");
}
void Module::Interface::InitializeApplicationInfo(Kernel::HLERequestContext& ctx) {
NGLOG_WARNING(Service_ACC, "(STUBBED) called");
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS);
}
void Module::Interface::GetBaasAccountManagerForApplication(Kernel::HLERequestContext& ctx) {
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(RESULT_SUCCESS);
rb.PushIpcInterface<IManagerForApplication>();
NGLOG_DEBUG(Service_ACC, "called");
}
void Module::Interface::GetLastOpenedUser(Kernel::HLERequestContext& ctx) {
NGLOG_WARNING(Service_ACC, "(STUBBED) called");
IPC::ResponseBuilder rb{ctx, 6};
rb.Push(RESULT_SUCCESS);
rb.PushRaw(DEFAULT_USER_ID);
}
Module::Interface::Interface(std::shared_ptr<Module> module, const char* name)
: ServiceFramework(name), module(std::move(module)) {}
void InstallInterfaces(SM::ServiceManager& service_manager) {
auto module = std::make_shared<Module>();
std::make_shared<ACC_AA>(module)->InstallAsService(service_manager);
std::make_shared<ACC_SU>(module)->InstallAsService(service_manager);
std::make_shared<ACC_U0>(module)->InstallAsService(service_manager);
std::make_shared<ACC_U1>(module)->InstallAsService(service_manager);
}
} // namespace Service::Account

View File

@@ -6,11 +6,28 @@
#include "core/hle/service/service.h"
namespace Service {
namespace Account {
namespace Service::Account {
class Module final {
public:
class Interface : public ServiceFramework<Interface> {
public:
Interface(std::shared_ptr<Module> module, const char* name);
void GetUserExistence(Kernel::HLERequestContext& ctx);
void ListAllUsers(Kernel::HLERequestContext& ctx);
void ListOpenUsers(Kernel::HLERequestContext& ctx);
void GetLastOpenedUser(Kernel::HLERequestContext& ctx);
void GetProfile(Kernel::HLERequestContext& ctx);
void InitializeApplicationInfo(Kernel::HLERequestContext& ctx);
void GetBaasAccountManagerForApplication(Kernel::HLERequestContext& ctx);
protected:
std::shared_ptr<Module> module;
};
};
/// Registers all ACC services with the specified service manager.
void InstallInterfaces(SM::ServiceManager& service_manager);
} // namespace Account
} // namespace Service
} // namespace Service::Account

View File

@@ -0,0 +1,20 @@
// Copyright 2018 yuzu emulator team
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#include "core/hle/service/acc/acc_aa.h"
namespace Service::Account {
ACC_AA::ACC_AA(std::shared_ptr<Module> module) : Module::Interface(std::move(module), "acc:aa") {
static const FunctionInfo functions[] = {
{0, nullptr, "EnsureCacheAsync"},
{1, nullptr, "LoadCache"},
{2, nullptr, "GetDeviceAccountId"},
{50, nullptr, "RegisterNotificationTokenAsync"},
{51, nullptr, "UnregisterNotificationTokenAsync"},
};
RegisterHandlers(functions);
}
} // namespace Service::Account

View File

@@ -0,0 +1,16 @@
// 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/acc/acc.h"
namespace Service::Account {
class ACC_AA final : public Module::Interface {
public:
explicit ACC_AA(std::shared_ptr<Module> module);
};
} // namespace Service::Account

View File

@@ -0,0 +1,53 @@
// Copyright 2018 yuzu emulator team
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#include "core/hle/service/acc/acc_su.h"
namespace Service::Account {
ACC_SU::ACC_SU(std::shared_ptr<Module> module) : Module::Interface(std::move(module), "acc:su") {
static const FunctionInfo functions[] = {
{0, nullptr, "GetUserCount"},
{1, &ACC_SU::GetUserExistence, "GetUserExistence"},
{2, &ACC_SU::ListAllUsers, "ListAllUsers"},
{3, &ACC_SU::ListOpenUsers, "ListOpenUsers"},
{4, &ACC_SU::GetLastOpenedUser, "GetLastOpenedUser"},
{5, &ACC_SU::GetProfile, "GetProfile"},
{6, nullptr, "GetProfileDigest"},
{50, nullptr, "IsUserRegistrationRequestPermitted"},
{51, nullptr, "TrySelectUserWithoutInteraction"},
{60, nullptr, "ListOpenContextStoredUsers"},
{100, nullptr, "GetUserRegistrationNotifier"},
{101, nullptr, "GetUserStateChangeNotifier"},
{102, nullptr, "GetBaasAccountManagerForSystemService"},
{103, nullptr, "GetBaasUserAvailabilityChangeNotifier"},
{104, nullptr, "GetProfileUpdateNotifier"},
{105, nullptr, "CheckNetworkServiceAvailabilityAsync"},
{110, nullptr, "StoreSaveDataThumbnail"},
{111, nullptr, "ClearSaveDataThumbnail"},
{112, nullptr, "LoadSaveDataThumbnail"},
{113, nullptr, "GetSaveDataThumbnailExistence"},
{190, nullptr, "GetUserLastOpenedApplication"},
{191, nullptr, "ActivateOpenContextHolder"},
{200, nullptr, "BeginUserRegistration"},
{201, nullptr, "CompleteUserRegistration"},
{202, nullptr, "CancelUserRegistration"},
{203, nullptr, "DeleteUser"},
{204, nullptr, "SetUserPosition"},
{205, nullptr, "GetProfileEditor"},
{206, nullptr, "CompleteUserRegistrationForcibly"},
{210, nullptr, "CreateFloatingRegistrationRequest"},
{230, nullptr, "AuthenticateServiceAsync"},
{250, nullptr, "GetBaasAccountAdministrator"},
{290, nullptr, "ProxyProcedureForGuestLoginWithNintendoAccount"},
{291, nullptr, "ProxyProcedureForFloatingRegistrationWithNintendoAccount"},
{299, nullptr, "SuspendBackgroundDaemon"},
{997, nullptr, "DebugInvalidateTokenCacheForUser"},
{998, nullptr, "DebugSetUserStateClose"},
{999, nullptr, "DebugSetUserStateOpen"},
};
RegisterHandlers(functions);
}
} // namespace Service::Account

View File

@@ -0,0 +1,18 @@
// 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/acc/acc.h"
namespace Service {
namespace Account {
class ACC_SU final : public Module::Interface {
public:
explicit ACC_SU(std::shared_ptr<Module> module);
};
} // namespace Account
} // namespace Service

View File

@@ -2,123 +2,32 @@
// 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/acc/acc_u0.h"
namespace Service {
namespace Account {
namespace Service::Account {
using Uid = std::array<u64, 2>;
static constexpr Uid DEFAULT_USER_ID{0x10ull, 0x20ull};
class IProfile final : public ServiceFramework<IProfile> {
public:
IProfile() : ServiceFramework("IProfile") {
static const FunctionInfo functions[] = {
{1, &IProfile::GetBase, "GetBase"},
};
RegisterHandlers(functions);
}
private:
void GetBase(Kernel::HLERequestContext& ctx) {
LOG_WARNING(Service_ACC, "(STUBBED) called");
ProfileBase profile_base{};
IPC::ResponseBuilder rb{ctx, 16};
rb.Push(RESULT_SUCCESS);
rb.PushRaw(profile_base);
}
};
class IManagerForApplication final : public ServiceFramework<IManagerForApplication> {
public:
IManagerForApplication() : ServiceFramework("IManagerForApplication") {
static const FunctionInfo functions[] = {
{0, &IManagerForApplication::CheckAvailability, "CheckAvailability"},
{1, &IManagerForApplication::GetAccountId, "GetAccountId"},
};
RegisterHandlers(functions);
}
private:
void CheckAvailability(Kernel::HLERequestContext& ctx) {
LOG_WARNING(Service_ACC, "(STUBBED) called");
IPC::ResponseBuilder rb{ctx, 3};
rb.Push(RESULT_SUCCESS);
rb.Push(true); // TODO: Check when this is supposed to return true and when not
}
void GetAccountId(Kernel::HLERequestContext& ctx) {
LOG_WARNING(Service_ACC, "(STUBBED) called");
IPC::ResponseBuilder rb{ctx, 4};
rb.Push(RESULT_SUCCESS);
rb.Push<u64>(0x12345678ABCDEF);
}
};
void ACC_U0::GetUserExistence(Kernel::HLERequestContext& ctx) {
LOG_WARNING(Service_ACC, "(STUBBED) called");
IPC::ResponseBuilder rb{ctx, 3};
rb.Push(RESULT_SUCCESS);
rb.Push(true); // TODO: Check when this is supposed to return true and when not
}
void ACC_U0::ListAllUsers(Kernel::HLERequestContext& ctx) {
LOG_WARNING(Service_ACC, "(STUBBED) called");
constexpr std::array<u128, 10> user_ids{DEFAULT_USER_ID};
ctx.WriteBuffer(user_ids.data(), user_ids.size());
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS);
}
void ACC_U0::ListOpenUsers(Kernel::HLERequestContext& ctx) {
LOG_WARNING(Service_ACC, "(STUBBED) called");
constexpr std::array<u128, 10> user_ids{DEFAULT_USER_ID};
ctx.WriteBuffer(user_ids.data(), user_ids.size());
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS);
}
void ACC_U0::GetProfile(Kernel::HLERequestContext& ctx) {
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(RESULT_SUCCESS);
rb.PushIpcInterface<IProfile>();
LOG_DEBUG(Service_ACC, "called");
}
void ACC_U0::InitializeApplicationInfo(Kernel::HLERequestContext& ctx) {
LOG_WARNING(Service_ACC, "(STUBBED) called");
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS);
}
void ACC_U0::GetBaasAccountManagerForApplication(Kernel::HLERequestContext& ctx) {
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(RESULT_SUCCESS);
rb.PushIpcInterface<IManagerForApplication>();
LOG_DEBUG(Service_ACC, "called");
}
void ACC_U0::GetLastOpenedUser(Kernel::HLERequestContext& ctx) {
LOG_WARNING(Service_ACC, "(STUBBED) called");
IPC::ResponseBuilder rb{ctx, 6};
rb.Push(RESULT_SUCCESS);
rb.PushRaw(DEFAULT_USER_ID);
}
ACC_U0::ACC_U0() : ServiceFramework("acc:u0") {
ACC_U0::ACC_U0(std::shared_ptr<Module> module) : Module::Interface(std::move(module), "acc:u0") {
static const FunctionInfo functions[] = {
{0, nullptr, "GetUserCount"},
{1, &ACC_U0::GetUserExistence, "GetUserExistence"},
{2, &ACC_U0::ListAllUsers, "ListAllUsers"},
{3, &ACC_U0::ListOpenUsers, "ListOpenUsers"},
{4, &ACC_U0::GetLastOpenedUser, "GetLastOpenedUser"},
{5, &ACC_U0::GetProfile, "GetProfile"},
{6, nullptr, "GetProfileDigest"},
{50, nullptr, "IsUserRegistrationRequestPermitted"},
{51, nullptr, "TrySelectUserWithoutInteraction"},
{60, nullptr, "ListOpenContextStoredUsers"},
{100, &ACC_U0::InitializeApplicationInfo, "InitializeApplicationInfo"},
{101, &ACC_U0::GetBaasAccountManagerForApplication, "GetBaasAccountManagerForApplication"},
{102, nullptr, "AuthenticateApplicationAsync"},
{103, nullptr, "CheckNetworkServiceAvailabilityAsync"},
{110, nullptr, "StoreSaveDataThumbnail"},
{111, nullptr, "ClearSaveDataThumbnail"},
{120, nullptr, "CreateGuestLoginRequest"},
{130, nullptr, "LoadOpenContext"},
};
RegisterHandlers(functions);
}
} // namespace Account
} // namespace Service
} // namespace Service::Account

View File

@@ -4,37 +4,13 @@
#pragma once
#include "core/hle/service/service.h"
#include "core/hle/service/acc/acc.h"
namespace Service {
namespace Account {
namespace Service::Account {
// TODO: RE this structure
struct UserData {
INSERT_PADDING_BYTES(0x80);
};
static_assert(sizeof(UserData) == 0x80, "UserData structure has incorrect size");
// TODO: RE this structure
struct ProfileBase {
INSERT_PADDING_BYTES(0x38);
};
static_assert(sizeof(ProfileBase) == 0x38, "ProfileBase structure has incorrect size");
class ACC_U0 final : public ServiceFramework<ACC_U0> {
class ACC_U0 final : public Module::Interface {
public:
ACC_U0();
~ACC_U0() = default;
private:
void GetUserExistence(Kernel::HLERequestContext& ctx);
void ListAllUsers(Kernel::HLERequestContext& ctx);
void ListOpenUsers(Kernel::HLERequestContext& ctx);
void GetLastOpenedUser(Kernel::HLERequestContext& ctx);
void GetProfile(Kernel::HLERequestContext& ctx);
void InitializeApplicationInfo(Kernel::HLERequestContext& ctx);
void GetBaasAccountManagerForApplication(Kernel::HLERequestContext& ctx);
explicit ACC_U0(std::shared_ptr<Module> module);
};
} // namespace Account
} // namespace Service
} // namespace Service::Account

View File

@@ -0,0 +1,40 @@
// Copyright 2018 yuzu emulator team
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#include "core/hle/service/acc/acc_u1.h"
namespace Service::Account {
ACC_U1::ACC_U1(std::shared_ptr<Module> module) : Module::Interface(std::move(module), "acc:u1") {
static const FunctionInfo functions[] = {
{0, nullptr, "GetUserCount"},
{1, &ACC_U1::GetUserExistence, "GetUserExistence"},
{2, &ACC_U1::ListAllUsers, "ListAllUsers"},
{3, &ACC_U1::ListOpenUsers, "ListOpenUsers"},
{4, &ACC_U1::GetLastOpenedUser, "GetLastOpenedUser"},
{5, &ACC_U1::GetProfile, "GetProfile"},
{6, nullptr, "GetProfileDigest"},
{50, nullptr, "IsUserRegistrationRequestPermitted"},
{51, nullptr, "TrySelectUserWithoutInteraction"},
{60, nullptr, "ListOpenContextStoredUsers"},
{100, nullptr, "GetUserRegistrationNotifier"},
{101, nullptr, "GetUserStateChangeNotifier"},
{102, nullptr, "GetBaasAccountManagerForSystemService"},
{103, nullptr, "GetProfileUpdateNotifier"},
{104, nullptr, "CheckNetworkServiceAvailabilityAsync"},
{105, nullptr, "GetBaasUserAvailabilityChangeNotifier"},
{110, nullptr, "StoreSaveDataThumbnail"},
{111, nullptr, "ClearSaveDataThumbnail"},
{112, nullptr, "LoadSaveDataThumbnail"},
{113, nullptr, "GetSaveDataThumbnailExistence"},
{190, nullptr, "GetUserLastOpenedApplication"},
{191, nullptr, "ActivateOpenContextHolder"},
{997, nullptr, "DebugInvalidateTokenCacheForUser"},
{998, nullptr, "DebugSetUserStateClose"},
{999, nullptr, "DebugSetUserStateOpen"},
};
RegisterHandlers(functions);
}
} // namespace Service::Account

View File

@@ -0,0 +1,16 @@
// 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/acc/acc.h"
namespace Service::Account {
class ACC_U1 final : public Module::Interface {
public:
explicit ACC_U1(std::shared_ptr<Module> module);
};
} // namespace Service::Account

View File

@@ -14,26 +14,28 @@
#include "core/hle/service/nvflinger/nvflinger.h"
#include "core/settings.h"
namespace Service {
namespace AM {
namespace Service::AM {
IWindowController::IWindowController() : ServiceFramework("IWindowController") {
static const FunctionInfo functions[] = {
{0, nullptr, "CreateWindow"},
{1, &IWindowController::GetAppletResourceUserId, "GetAppletResourceUserId"},
{10, &IWindowController::AcquireForegroundRights, "AcquireForegroundRights"},
{11, nullptr, "ReleaseForegroundRights"},
{12, nullptr, "RejectToChangeIntoBackground"},
};
RegisterHandlers(functions);
}
void IWindowController::GetAppletResourceUserId(Kernel::HLERequestContext& ctx) {
LOG_WARNING(Service_AM, "(STUBBED) called");
NGLOG_WARNING(Service_AM, "(STUBBED) called");
IPC::ResponseBuilder rb{ctx, 4};
rb.Push(RESULT_SUCCESS);
rb.Push<u64>(0);
}
void IWindowController::AcquireForegroundRights(Kernel::HLERequestContext& ctx) {
LOG_WARNING(Service_AM, "(STUBBED) called");
NGLOG_WARNING(Service_AM, "(STUBBED) called");
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS);
}
@@ -52,20 +54,20 @@ IAudioController::IAudioController() : ServiceFramework("IAudioController") {
}
void IAudioController::SetExpectedMasterVolume(Kernel::HLERequestContext& ctx) {
LOG_WARNING(Service_AM, "(STUBBED) called");
NGLOG_WARNING(Service_AM, "(STUBBED) called");
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS);
}
void IAudioController::GetMainAppletExpectedMasterVolume(Kernel::HLERequestContext& ctx) {
LOG_WARNING(Service_AM, "(STUBBED) called");
NGLOG_WARNING(Service_AM, "(STUBBED) called");
IPC::ResponseBuilder rb{ctx, 3};
rb.Push(RESULT_SUCCESS);
rb.Push(volume);
}
void IAudioController::GetLibraryAppletExpectedMasterVolume(Kernel::HLERequestContext& ctx) {
LOG_WARNING(Service_AM, "(STUBBED) called");
NGLOG_WARNING(Service_AM, "(STUBBED) called");
IPC::ResponseBuilder rb{ctx, 3};
rb.Push(RESULT_SUCCESS);
rb.Push(volume);
@@ -78,8 +80,11 @@ IDebugFunctions::IDebugFunctions() : ServiceFramework("IDebugFunctions") {}
ISelfController::ISelfController(std::shared_ptr<NVFlinger::NVFlinger> nvflinger)
: ServiceFramework("ISelfController"), nvflinger(std::move(nvflinger)) {
static const FunctionInfo functions[] = {
{0, nullptr, "Exit"},
{1, &ISelfController::LockExit, "LockExit"},
{2, &ISelfController::UnlockExit, "UnlockExit"},
{3, nullptr, "EnterFatalSection"},
{4, nullptr, "LeaveFatalSection"},
{9, &ISelfController::GetLibraryAppletLaunchableEvent, "GetLibraryAppletLaunchableEvent"},
{10, &ISelfController::SetScreenShotPermission, "SetScreenShotPermission"},
{11, &ISelfController::SetOperationModeChangedNotification,
@@ -88,8 +93,29 @@ ISelfController::ISelfController(std::shared_ptr<NVFlinger::NVFlinger> nvflinger
"SetPerformanceModeChangedNotification"},
{13, &ISelfController::SetFocusHandlingMode, "SetFocusHandlingMode"},
{14, &ISelfController::SetRestartMessageEnabled, "SetRestartMessageEnabled"},
{15, nullptr, "SetScreenShotAppletIdentityInfo"},
{16, &ISelfController::SetOutOfFocusSuspendingEnabled, "SetOutOfFocusSuspendingEnabled"},
{17, nullptr, "SetControllerFirmwareUpdateSection"},
{18, nullptr, "SetRequiresCaptureButtonShortPressedMessage"},
{19, nullptr, "SetScreenShotImageOrientation"},
{20, nullptr, "SetDesirableKeyboardLayout"},
{40, &ISelfController::CreateManagedDisplayLayer, "CreateManagedDisplayLayer"},
{41, nullptr, "IsSystemBufferSharingEnabled"},
{42, nullptr, "GetSystemSharedLayerHandle"},
{50, nullptr, "SetHandlesRequestToDisplay"},
{51, nullptr, "ApproveToDisplay"},
{60, nullptr, "OverrideAutoSleepTimeAndDimmingTime"},
{61, nullptr, "SetMediaPlaybackState"},
{62, nullptr, "SetIdleTimeDetectionExtension"},
{63, nullptr, "GetIdleTimeDetectionExtension"},
{64, nullptr, "SetInputDetectionSourceSet"},
{65, nullptr, "ReportUserIsActive"},
{66, nullptr, "GetCurrentIlluminance"},
{67, nullptr, "IsIlluminanceAvailable"},
{68, nullptr, "SetAutoSleepDisabled"},
{69, nullptr, "IsAutoSleepDisabled"},
{70, nullptr, "ReportMultimediaError"},
{80, nullptr, "SetWirelessPriorityMode"},
};
RegisterHandlers(functions);
@@ -113,14 +139,14 @@ void ISelfController::SetFocusHandlingMode(Kernel::HLERequestContext& ctx) {
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS);
LOG_WARNING(Service_AM, "(STUBBED) called");
NGLOG_WARNING(Service_AM, "(STUBBED) called");
}
void ISelfController::SetRestartMessageEnabled(Kernel::HLERequestContext& ctx) {
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS);
LOG_WARNING(Service_AM, "(STUBBED) called");
NGLOG_WARNING(Service_AM, "(STUBBED) called");
}
void ISelfController::SetPerformanceModeChangedNotification(Kernel::HLERequestContext& ctx) {
@@ -131,14 +157,14 @@ void ISelfController::SetPerformanceModeChangedNotification(Kernel::HLERequestCo
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS);
LOG_WARNING(Service_AM, "(STUBBED) called flag=%u", static_cast<u32>(flag));
NGLOG_WARNING(Service_AM, "(STUBBED) called flag={}", flag);
}
void ISelfController::SetScreenShotPermission(Kernel::HLERequestContext& ctx) {
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS);
LOG_WARNING(Service_AM, "(STUBBED) called");
NGLOG_WARNING(Service_AM, "(STUBBED) called");
}
void ISelfController::SetOperationModeChangedNotification(Kernel::HLERequestContext& ctx) {
@@ -149,7 +175,7 @@ void ISelfController::SetOperationModeChangedNotification(Kernel::HLERequestCont
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS);
LOG_WARNING(Service_AM, "(STUBBED) called flag=%u", static_cast<u32>(flag));
NGLOG_WARNING(Service_AM, "(STUBBED) called flag={}", flag);
}
void ISelfController::SetOutOfFocusSuspendingEnabled(Kernel::HLERequestContext& ctx) {
@@ -162,21 +188,21 @@ void ISelfController::SetOutOfFocusSuspendingEnabled(Kernel::HLERequestContext&
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS);
LOG_WARNING(Service_AM, "(STUBBED) called enabled=%u", static_cast<u32>(enabled));
NGLOG_WARNING(Service_AM, "(STUBBED) called enabled={}", enabled);
}
void ISelfController::LockExit(Kernel::HLERequestContext& ctx) {
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS);
LOG_WARNING(Service_AM, "(STUBBED) called");
NGLOG_WARNING(Service_AM, "(STUBBED) called");
}
void ISelfController::UnlockExit(Kernel::HLERequestContext& ctx) {
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS);
LOG_WARNING(Service_AM, "(STUBBED) called");
NGLOG_WARNING(Service_AM, "(STUBBED) called");
}
void ISelfController::GetLibraryAppletLaunchableEvent(Kernel::HLERequestContext& ctx) {
@@ -186,7 +212,7 @@ void ISelfController::GetLibraryAppletLaunchableEvent(Kernel::HLERequestContext&
rb.Push(RESULT_SUCCESS);
rb.PushCopyObjects(launchable_event);
LOG_WARNING(Service_AM, "(STUBBED) called");
NGLOG_WARNING(Service_AM, "(STUBBED) called");
}
void ISelfController::CreateManagedDisplayLayer(Kernel::HLERequestContext& ctx) {
@@ -199,16 +225,37 @@ void ISelfController::CreateManagedDisplayLayer(Kernel::HLERequestContext& ctx)
rb.Push(RESULT_SUCCESS);
rb.Push(layer_id);
LOG_WARNING(Service_AM, "(STUBBED) called");
NGLOG_WARNING(Service_AM, "(STUBBED) called");
}
ICommonStateGetter::ICommonStateGetter() : ServiceFramework("ICommonStateGetter") {
static const FunctionInfo functions[] = {
{0, &ICommonStateGetter::GetEventHandle, "GetEventHandle"},
{1, &ICommonStateGetter::ReceiveMessage, "ReceiveMessage"},
{2, nullptr, "GetThisAppletKind"},
{3, nullptr, "AllowToEnterSleep"},
{4, nullptr, "DisallowToEnterSleep"},
{5, &ICommonStateGetter::GetOperationMode, "GetOperationMode"},
{6, &ICommonStateGetter::GetPerformanceMode, "GetPerformanceMode"},
{7, nullptr, "GetCradleStatus"},
{8, nullptr, "GetBootMode"},
{9, &ICommonStateGetter::GetCurrentFocusState, "GetCurrentFocusState"},
{10, nullptr, "RequestToAcquireSleepLock"},
{11, nullptr, "ReleaseSleepLock"},
{12, nullptr, "ReleaseSleepLockTransiently"},
{13, nullptr, "GetAcquiredSleepLockEvent"},
{20, nullptr, "PushToGeneralChannel"},
{30, nullptr, "GetHomeButtonReaderLockAccessor"},
{31, nullptr, "GetReaderLockAccessorEx"},
{40, nullptr, "GetCradleFwVersion"},
{50, nullptr, "IsVrModeEnabled"},
{51, nullptr, "SetVrModeEnabled"},
{52, nullptr, "SwitchLcdBacklight"},
{55, nullptr, "IsInControllerFirmwareUpdateSection"},
{60, nullptr, "GetDefaultDisplayResolution"},
{61, nullptr, "GetDefaultDisplayResolutionChangeEvent"},
{62, nullptr, "GetHdcpAuthenticationState"},
{63, nullptr, "GetHdcpAuthenticationStateChangeEvent"},
};
RegisterHandlers(functions);
@@ -222,7 +269,7 @@ void ICommonStateGetter::GetEventHandle(Kernel::HLERequestContext& ctx) {
rb.Push(RESULT_SUCCESS);
rb.PushCopyObjects(event);
LOG_WARNING(Service_AM, "(STUBBED) called");
NGLOG_WARNING(Service_AM, "(STUBBED) called");
}
void ICommonStateGetter::ReceiveMessage(Kernel::HLERequestContext& ctx) {
@@ -230,7 +277,7 @@ void ICommonStateGetter::ReceiveMessage(Kernel::HLERequestContext& ctx) {
rb.Push(RESULT_SUCCESS);
rb.Push<u32>(15);
LOG_WARNING(Service_AM, "(STUBBED) called");
NGLOG_WARNING(Service_AM, "(STUBBED) called");
}
void ICommonStateGetter::GetCurrentFocusState(Kernel::HLERequestContext& ctx) {
@@ -238,7 +285,7 @@ void ICommonStateGetter::GetCurrentFocusState(Kernel::HLERequestContext& ctx) {
rb.Push(RESULT_SUCCESS);
rb.Push(static_cast<u8>(FocusState::InFocus));
LOG_WARNING(Service_AM, "(STUBBED) called");
NGLOG_WARNING(Service_AM, "(STUBBED) called");
}
void ICommonStateGetter::GetOperationMode(Kernel::HLERequestContext& ctx) {
@@ -247,7 +294,7 @@ void ICommonStateGetter::GetOperationMode(Kernel::HLERequestContext& ctx) {
rb.Push(RESULT_SUCCESS);
rb.Push(static_cast<u8>(use_docked_mode ? OperationMode::Docked : OperationMode::Handheld));
LOG_WARNING(Service_AM, "(STUBBED) called");
NGLOG_WARNING(Service_AM, "(STUBBED) called");
}
void ICommonStateGetter::GetPerformanceMode(Kernel::HLERequestContext& ctx) {
@@ -257,7 +304,7 @@ void ICommonStateGetter::GetPerformanceMode(Kernel::HLERequestContext& ctx) {
rb.Push(static_cast<u32>(use_docked_mode ? APM::PerformanceMode::Docked
: APM::PerformanceMode::Handheld));
LOG_WARNING(Service_AM, "(STUBBED) called");
NGLOG_WARNING(Service_AM, "(STUBBED) called");
}
class ILibraryAppletAccessor final : public ServiceFramework<ILibraryAppletAccessor> {
@@ -278,7 +325,7 @@ public:
{104, nullptr, "PopInteractiveOutData"},
{105, nullptr, "GetPopOutDataEvent"},
{106, nullptr, "GetPopInteractiveOutDataEvent"},
{120, nullptr, "NeedsToExitProcess"},
{110, nullptr, "NeedsToExitProcess"},
{120, nullptr, "GetLibraryAppletInfo"},
{150, nullptr, "RequestForAppletToGetForeground"},
{160, nullptr, "GetIndirectLayerConsumerHandle"},
@@ -297,7 +344,7 @@ private:
rb.Push(RESULT_SUCCESS);
rb.PushCopyObjects(state_changed_event);
LOG_WARNING(Service_AM, "(STUBBED) called");
NGLOG_WARNING(Service_AM, "(STUBBED) called");
}
Kernel::SharedPtr<Kernel::Event> state_changed_event;
@@ -321,7 +368,7 @@ void ILibraryAppletCreator::CreateLibraryApplet(Kernel::HLERequestContext& ctx)
rb.Push(RESULT_SUCCESS);
rb.PushIpcInterface<AM::ILibraryAppletAccessor>();
LOG_DEBUG(Service_AM, "called");
NGLOG_DEBUG(Service_AM, "called");
}
class IStorageAccessor final : public ServiceFramework<IStorageAccessor> {
@@ -330,6 +377,7 @@ public:
: ServiceFramework("IStorageAccessor"), buffer(std::move(buffer)) {
static const FunctionInfo functions[] = {
{0, &IStorageAccessor::GetSize, "GetSize"},
{10, nullptr, "Write"},
{11, &IStorageAccessor::Read, "Read"},
};
RegisterHandlers(functions);
@@ -344,7 +392,7 @@ private:
rb.Push(RESULT_SUCCESS);
rb.Push(static_cast<u64>(buffer.size()));
LOG_DEBUG(Service_AM, "called");
NGLOG_DEBUG(Service_AM, "called");
}
void Read(Kernel::HLERequestContext& ctx) {
@@ -362,7 +410,7 @@ private:
rb.Push(RESULT_SUCCESS);
LOG_DEBUG(Service_AM, "called");
NGLOG_DEBUG(Service_AM, "called");
}
};
@@ -372,6 +420,7 @@ public:
: ServiceFramework("IStorage"), buffer(std::move(buffer)) {
static const FunctionInfo functions[] = {
{0, &IStorage::Open, "Open"},
{1, nullptr, "OpenTransferStorage"},
};
RegisterHandlers(functions);
}
@@ -385,19 +434,49 @@ private:
rb.Push(RESULT_SUCCESS);
rb.PushIpcInterface<AM::IStorageAccessor>(buffer);
LOG_DEBUG(Service_AM, "called");
NGLOG_DEBUG(Service_AM, "called");
}
};
IApplicationFunctions::IApplicationFunctions() : ServiceFramework("IApplicationFunctions") {
static const FunctionInfo functions[] = {
{1, &IApplicationFunctions::PopLaunchParameter, "PopLaunchParameter"},
{10, nullptr, "CreateApplicationAndPushAndRequestToStart"},
{11, nullptr, "CreateApplicationAndPushAndRequestToStartForQuest"},
{12, nullptr, "CreateApplicationAndRequestToStart"},
{13, nullptr, "CreateApplicationAndRequestToStartForQuest"},
{20, &IApplicationFunctions::EnsureSaveData, "EnsureSaveData"},
{21, &IApplicationFunctions::GetDesiredLanguage, "GetDesiredLanguage"},
{22, &IApplicationFunctions::SetTerminateResult, "SetTerminateResult"},
{23, nullptr, "GetDisplayVersion"},
{24, nullptr, "GetLaunchStorageInfoForDebug"},
{25, nullptr, "ExtendSaveData"},
{26, nullptr, "GetSaveDataSize"},
{30, nullptr, "BeginBlockingHomeButtonShortAndLongPressed"},
{31, nullptr, "EndBlockingHomeButtonShortAndLongPressed"},
{32, nullptr, "BeginBlockingHomeButton"},
{33, nullptr, "EndBlockingHomeButton"},
{40, &IApplicationFunctions::NotifyRunning, "NotifyRunning"},
{50, nullptr, "GetPseudoDeviceId"},
{60, nullptr, "SetMediaPlaybackStateForApplication"},
{65, nullptr, "IsGamePlayRecordingSupported"},
{66, &IApplicationFunctions::InitializeGamePlayRecording, "InitializeGamePlayRecording"},
{67, &IApplicationFunctions::SetGamePlayRecordingState, "SetGamePlayRecordingState"},
{40, &IApplicationFunctions::NotifyRunning, "NotifyRunning"},
{68, nullptr, "RequestFlushGamePlayingMovieForDebug"},
{70, nullptr, "RequestToShutdown"},
{71, nullptr, "RequestToReboot"},
{80, nullptr, "ExitAndRequestToShowThanksMessage"},
{90, nullptr, "EnableApplicationCrashReport"},
{100, nullptr, "InitializeApplicationCopyrightFrameBuffer"},
{101, nullptr, "SetApplicationCopyrightImage"},
{102, nullptr, "SetApplicationCopyrightVisibility"},
{110, nullptr, "QueryApplicationPlayStatistics"},
{120, nullptr, "ExecuteProgram"},
{121, nullptr, "ClearUserChannel"},
{122, nullptr, "UnpopToUserChannel"},
{500, nullptr, "StartContinuousRecordingFlushForDebug"},
{1000, nullptr, "CreateMovieMaker"},
{1001, nullptr, "PrepareForJit"},
};
RegisterHandlers(functions);
}
@@ -419,14 +498,14 @@ void IApplicationFunctions::PopLaunchParameter(Kernel::HLERequestContext& ctx) {
rb.Push(RESULT_SUCCESS);
rb.PushIpcInterface<AM::IStorage>(buffer);
LOG_DEBUG(Service_AM, "called");
NGLOG_DEBUG(Service_AM, "called");
}
void IApplicationFunctions::EnsureSaveData(Kernel::HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
u128 uid = rp.PopRaw<u128>();
LOG_WARNING(Service, "(STUBBED) called uid = %016" PRIX64 "%016" PRIX64, uid[1], uid[0]);
NGLOG_WARNING(Service, "(STUBBED) called uid = {:016X}{:016X}", uid[1], uid[0]);
IPC::ResponseBuilder rb{ctx, 4};
@@ -454,27 +533,27 @@ void IApplicationFunctions::SetTerminateResult(Kernel::HLERequestContext& ctx) {
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS);
LOG_WARNING(Service_AM, "(STUBBED) called, result=0x%08X", result);
NGLOG_WARNING(Service_AM, "(STUBBED) called, result={:#010}", result);
}
void IApplicationFunctions::GetDesiredLanguage(Kernel::HLERequestContext& ctx) {
IPC::ResponseBuilder rb{ctx, 4};
rb.Push(RESULT_SUCCESS);
rb.Push<u64>(SystemLanguage::English);
LOG_WARNING(Service_AM, "(STUBBED) called");
NGLOG_WARNING(Service_AM, "(STUBBED) called");
}
void IApplicationFunctions::InitializeGamePlayRecording(Kernel::HLERequestContext& ctx) {
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS);
LOG_WARNING(Service_AM, "(STUBBED) called");
NGLOG_WARNING(Service_AM, "(STUBBED) called");
}
void IApplicationFunctions::SetGamePlayRecordingState(Kernel::HLERequestContext& ctx) {
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS);
LOG_WARNING(Service_AM, "(STUBBED) called");
NGLOG_WARNING(Service_AM, "(STUBBED) called");
}
void IApplicationFunctions::NotifyRunning(Kernel::HLERequestContext& ctx) {
@@ -482,7 +561,7 @@ void IApplicationFunctions::NotifyRunning(Kernel::HLERequestContext& ctx) {
rb.Push(RESULT_SUCCESS);
rb.Push<u8>(0); // Unknown, seems to be ignored by official processes
LOG_WARNING(Service_AM, "(STUBBED) called");
NGLOG_WARNING(Service_AM, "(STUBBED) called");
}
void InstallInterfaces(SM::ServiceManager& service_manager,
@@ -491,5 +570,4 @@ void InstallInterfaces(SM::ServiceManager& service_manager,
std::make_shared<AppletOE>(nvflinger)->InstallAsService(service_manager);
}
} // namespace AM
} // namespace Service
} // namespace Service::AM

View File

@@ -8,8 +8,7 @@
#include "core/hle/service/am/applet_ae.h"
#include "core/hle/service/nvflinger/nvflinger.h"
namespace Service {
namespace AM {
namespace Service::AM {
class ILibraryAppletProxy final : public ServiceFramework<ILibraryAppletProxy> {
public:
@@ -21,6 +20,7 @@ public:
{2, &ILibraryAppletProxy::GetWindowController, "GetWindowController"},
{3, &ILibraryAppletProxy::GetAudioController, "GetAudioController"},
{4, &ILibraryAppletProxy::GetDisplayController, "GetDisplayController"},
{10, nullptr, "GetProcessWindingController"},
{11, &ILibraryAppletProxy::GetLibraryAppletCreator, "GetLibraryAppletCreator"},
{20, &ILibraryAppletProxy::GetApplicationFunctions, "GetApplicationFunctions"},
{1000, &ILibraryAppletProxy::GetDebugFunctions, "GetDebugFunctions"},
@@ -33,56 +33,56 @@ private:
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(RESULT_SUCCESS);
rb.PushIpcInterface<ICommonStateGetter>();
LOG_DEBUG(Service_AM, "called");
NGLOG_DEBUG(Service_AM, "called");
}
void GetSelfController(Kernel::HLERequestContext& ctx) {
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(RESULT_SUCCESS);
rb.PushIpcInterface<ISelfController>(nvflinger);
LOG_DEBUG(Service_AM, "called");
NGLOG_DEBUG(Service_AM, "called");
}
void GetWindowController(Kernel::HLERequestContext& ctx) {
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(RESULT_SUCCESS);
rb.PushIpcInterface<IWindowController>();
LOG_DEBUG(Service_AM, "called");
NGLOG_DEBUG(Service_AM, "called");
}
void GetAudioController(Kernel::HLERequestContext& ctx) {
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(RESULT_SUCCESS);
rb.PushIpcInterface<IAudioController>();
LOG_DEBUG(Service_AM, "called");
NGLOG_DEBUG(Service_AM, "called");
}
void GetDisplayController(Kernel::HLERequestContext& ctx) {
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(RESULT_SUCCESS);
rb.PushIpcInterface<IDisplayController>();
LOG_DEBUG(Service_AM, "called");
NGLOG_DEBUG(Service_AM, "called");
}
void GetDebugFunctions(Kernel::HLERequestContext& ctx) {
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(RESULT_SUCCESS);
rb.PushIpcInterface<IDebugFunctions>();
LOG_DEBUG(Service_AM, "called");
NGLOG_DEBUG(Service_AM, "called");
}
void GetLibraryAppletCreator(Kernel::HLERequestContext& ctx) {
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(RESULT_SUCCESS);
rb.PushIpcInterface<ILibraryAppletCreator>();
LOG_DEBUG(Service_AM, "called");
NGLOG_DEBUG(Service_AM, "called");
}
void GetApplicationFunctions(Kernel::HLERequestContext& ctx) {
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(RESULT_SUCCESS);
rb.PushIpcInterface<IApplicationFunctions>();
LOG_DEBUG(Service_AM, "called");
NGLOG_DEBUG(Service_AM, "called");
}
std::shared_ptr<NVFlinger::NVFlinger> nvflinger;
@@ -92,7 +92,7 @@ void AppletAE::OpenLibraryAppletProxyOld(Kernel::HLERequestContext& ctx) {
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(RESULT_SUCCESS);
rb.PushIpcInterface<ILibraryAppletProxy>(nvflinger);
LOG_DEBUG(Service_AM, "called");
NGLOG_DEBUG(Service_AM, "called");
}
AppletAE::AppletAE(std::shared_ptr<NVFlinger::NVFlinger> nvflinger)
@@ -108,5 +108,4 @@ AppletAE::AppletAE(std::shared_ptr<NVFlinger::NVFlinger> nvflinger)
RegisterHandlers(functions);
}
} // namespace AM
} // namespace Service
} // namespace Service::AM

View File

@@ -8,8 +8,7 @@
#include "core/hle/service/am/applet_oe.h"
#include "core/hle/service/nvflinger/nvflinger.h"
namespace Service {
namespace AM {
namespace Service::AM {
class IApplicationProxy final : public ServiceFramework<IApplicationProxy> {
public:
@@ -21,6 +20,7 @@ public:
{2, &IApplicationProxy::GetWindowController, "GetWindowController"},
{3, &IApplicationProxy::GetAudioController, "GetAudioController"},
{4, &IApplicationProxy::GetDisplayController, "GetDisplayController"},
{10, nullptr, "GetProcessWindingController"},
{11, &IApplicationProxy::GetLibraryAppletCreator, "GetLibraryAppletCreator"},
{20, &IApplicationProxy::GetApplicationFunctions, "GetApplicationFunctions"},
{1000, &IApplicationProxy::GetDebugFunctions, "GetDebugFunctions"},
@@ -33,56 +33,56 @@ private:
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(RESULT_SUCCESS);
rb.PushIpcInterface<IAudioController>();
LOG_DEBUG(Service_AM, "called");
NGLOG_DEBUG(Service_AM, "called");
}
void GetDisplayController(Kernel::HLERequestContext& ctx) {
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(RESULT_SUCCESS);
rb.PushIpcInterface<IDisplayController>();
LOG_DEBUG(Service_AM, "called");
NGLOG_DEBUG(Service_AM, "called");
}
void GetDebugFunctions(Kernel::HLERequestContext& ctx) {
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(RESULT_SUCCESS);
rb.PushIpcInterface<IDebugFunctions>();
LOG_DEBUG(Service_AM, "called");
NGLOG_DEBUG(Service_AM, "called");
}
void GetWindowController(Kernel::HLERequestContext& ctx) {
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(RESULT_SUCCESS);
rb.PushIpcInterface<IWindowController>();
LOG_DEBUG(Service_AM, "called");
NGLOG_DEBUG(Service_AM, "called");
}
void GetSelfController(Kernel::HLERequestContext& ctx) {
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(RESULT_SUCCESS);
rb.PushIpcInterface<ISelfController>(nvflinger);
LOG_DEBUG(Service_AM, "called");
NGLOG_DEBUG(Service_AM, "called");
}
void GetCommonStateGetter(Kernel::HLERequestContext& ctx) {
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(RESULT_SUCCESS);
rb.PushIpcInterface<ICommonStateGetter>();
LOG_DEBUG(Service_AM, "called");
NGLOG_DEBUG(Service_AM, "called");
}
void GetLibraryAppletCreator(Kernel::HLERequestContext& ctx) {
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(RESULT_SUCCESS);
rb.PushIpcInterface<ILibraryAppletCreator>();
LOG_DEBUG(Service_AM, "called");
NGLOG_DEBUG(Service_AM, "called");
}
void GetApplicationFunctions(Kernel::HLERequestContext& ctx) {
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(RESULT_SUCCESS);
rb.PushIpcInterface<IApplicationFunctions>();
LOG_DEBUG(Service_AM, "called");
NGLOG_DEBUG(Service_AM, "called");
}
std::shared_ptr<NVFlinger::NVFlinger> nvflinger;
@@ -92,7 +92,7 @@ void AppletOE::OpenApplicationProxy(Kernel::HLERequestContext& ctx) {
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(RESULT_SUCCESS);
rb.PushIpcInterface<IApplicationProxy>(nvflinger);
LOG_DEBUG(Service_AM, "called");
NGLOG_DEBUG(Service_AM, "called");
}
AppletOE::AppletOE(std::shared_ptr<NVFlinger::NVFlinger> nvflinger)
@@ -103,5 +103,4 @@ AppletOE::AppletOE(std::shared_ptr<NVFlinger::NVFlinger> nvflinger)
RegisterHandlers(functions);
}
} // namespace AM
} // namespace Service
} // namespace Service::AM

View File

@@ -6,8 +6,7 @@
#include "core/hle/ipc_helpers.h"
#include "core/hle/service/aoc/aoc_u.h"
namespace Service {
namespace AOC {
namespace Service::AOC {
AOC_U::AOC_U() : ServiceFramework("aoc:u") {
static const FunctionInfo functions[] = {
@@ -19,6 +18,7 @@ AOC_U::AOC_U() : ServiceFramework("aoc:u") {
{5, nullptr, "GetAddOnContentBaseId"},
{6, nullptr, "PrepareAddOnContentByApplicationId"},
{7, nullptr, "PrepareAddOnContent"},
{8, nullptr, "GetAddOnContentListChangedEvent"},
};
RegisterHandlers(functions);
}
@@ -27,19 +27,18 @@ void AOC_U::CountAddOnContent(Kernel::HLERequestContext& ctx) {
IPC::ResponseBuilder rb{ctx, 4};
rb.Push(RESULT_SUCCESS);
rb.Push<u64>(0);
LOG_WARNING(Service_AOC, "(STUBBED) called");
NGLOG_WARNING(Service_AOC, "(STUBBED) called");
}
void AOC_U::ListAddOnContent(Kernel::HLERequestContext& ctx) {
IPC::ResponseBuilder rb{ctx, 4};
rb.Push(RESULT_SUCCESS);
rb.Push<u64>(0);
LOG_WARNING(Service_AOC, "(STUBBED) called");
NGLOG_WARNING(Service_AOC, "(STUBBED) called");
}
void InstallInterfaces(SM::ServiceManager& service_manager) {
std::make_shared<AOC_U>()->InstallAsService(service_manager);
}
} // namespace AOC
} // namespace Service
} // namespace Service::AOC

View File

@@ -6,8 +6,7 @@
#include "core/hle/service/service.h"
namespace Service {
namespace AOC {
namespace Service::AOC {
class AOC_U final : public ServiceFramework<AOC_U> {
public:
@@ -22,5 +21,4 @@ private:
/// Registers all AOC services with the specified service manager.
void InstallInterfaces(SM::ServiceManager& service_manager);
} // namespace AOC
} // namespace Service
} // namespace Service::AOC

View File

@@ -7,8 +7,7 @@
#include "core/hle/service/apm/apm.h"
#include "core/hle/service/apm/interface.h"
namespace Service {
namespace APM {
namespace Service::APM {
void InstallInterfaces(SM::ServiceManager& service_manager) {
auto module_ = std::make_shared<Module>();
@@ -16,5 +15,4 @@ void InstallInterfaces(SM::ServiceManager& service_manager) {
std::make_shared<APM>(module_, "apm:p")->InstallAsService(service_manager);
}
} // namespace APM
} // namespace Service
} // namespace Service::APM

View File

@@ -6,8 +6,7 @@
#include "core/hle/service/service.h"
namespace Service {
namespace APM {
namespace Service::APM {
enum class PerformanceMode : u8 {
Handheld = 0,
@@ -23,5 +22,4 @@ public:
/// Registers all AM services with the specified service manager.
void InstallInterfaces(SM::ServiceManager& service_manager);
} // namespace APM
} // namespace Service
} // namespace Service::APM

View File

@@ -7,8 +7,7 @@
#include "core/hle/service/apm/apm.h"
#include "core/hle/service/apm/interface.h"
namespace Service {
namespace APM {
namespace Service::APM {
class ISession final : public ServiceFramework<ISession> {
public:
@@ -30,8 +29,8 @@ private:
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS);
LOG_WARNING(Service_APM, "(STUBBED) called mode=%u config=%u", static_cast<u32>(mode),
config);
NGLOG_WARNING(Service_APM, "(STUBBED) called mode={} config={}", static_cast<u32>(mode),
config);
}
void GetPerformanceConfiguration(Kernel::HLERequestContext& ctx) {
@@ -43,7 +42,7 @@ private:
rb.Push(RESULT_SUCCESS);
rb.Push<u32>(0); // Performance configuration
LOG_WARNING(Service_APM, "(STUBBED) called mode=%u", static_cast<u32>(mode));
NGLOG_WARNING(Service_APM, "(STUBBED) called mode={}", static_cast<u32>(mode));
}
};
@@ -62,5 +61,4 @@ void APM::OpenSession(Kernel::HLERequestContext& ctx) {
rb.PushIpcInterface<ISession>();
}
} // namespace APM
} // namespace Service
} // namespace Service::APM

View File

@@ -6,8 +6,7 @@
#include "core/hle/service/service.h"
namespace Service {
namespace APM {
namespace Service::APM {
class APM final : public ServiceFramework<APM> {
public:
@@ -23,5 +22,4 @@ private:
/// Registers all AM services with the specified service manager.
void InstallInterfaces(SM::ServiceManager& service_manager);
} // namespace APM
} // namespace Service
} // namespace Service::APM

View File

@@ -7,22 +7,26 @@
#include "core/hle/kernel/hle_ipc.h"
#include "core/hle/service/audio/audin_u.h"
namespace Service {
namespace Audio {
namespace Service::Audio {
class IAudioIn final : public ServiceFramework<IAudioIn> {
public:
IAudioIn() : ServiceFramework("IAudioIn") {
static const FunctionInfo functions[] = {
{0x0, nullptr, "GetAudioInState"},
{0x1, nullptr, "StartAudioIn"},
{0x2, nullptr, "StopAudioIn"},
{0x3, nullptr, "AppendAudioInBuffer_1"},
{0x4, nullptr, "RegisterBufferEvent"},
{0x5, nullptr, "GetReleasedAudioInBuffer_1"},
{0x6, nullptr, "ContainsAudioInBuffer"},
{0x7, nullptr, "AppendAudioInBuffer_2"},
{0x8, nullptr, "GetReleasedAudioInBuffer_2"},
{0, nullptr, "GetAudioInState"},
{1, nullptr, "StartAudioIn"},
{2, nullptr, "StopAudioIn"},
{3, nullptr, "AppendAudioInBuffer"},
{4, nullptr, "RegisterBufferEvent"},
{5, nullptr, "GetReleasedAudioInBuffer"},
{6, nullptr, "ContainsAudioInBuffer"},
{7, nullptr, "AppendAudioInBufferWithUserEvent"},
{8, nullptr, "AppendAudioInBufferAuto"},
{9, nullptr, "GetReleasedAudioInBufferAuto"},
{10, nullptr, "AppendAudioInBufferWithUserEventAuto"},
{11, nullptr, "GetAudioInBufferCount"},
{12, nullptr, "SetAudioInDeviceGain"},
{13, nullptr, "GetAudioInDeviceGain"},
};
RegisterHandlers(functions);
}
@@ -31,11 +35,12 @@ public:
AudInU::AudInU() : ServiceFramework("audin:u") {
static const FunctionInfo functions[] = {
{0x00000000, nullptr, "ListAudioIns"},
{0x00000001, nullptr, "OpenAudioIn"},
{0, nullptr, "ListAudioIns"},
{1, nullptr, "OpenAudioIn"},
{3, nullptr, "OpenAudioInAuto"},
{4, nullptr, "ListAudioInsAuto"},
};
RegisterHandlers(functions);
}
} // namespace Audio
} // namespace Service
} // namespace Service::Audio

View File

@@ -10,8 +10,7 @@ namespace Kernel {
class HLERequestContext;
}
namespace Service {
namespace Audio {
namespace Service::Audio {
class AudInU final : public ServiceFramework<AudInU> {
public:
@@ -19,5 +18,4 @@ public:
~AudInU() = default;
};
} // namespace Audio
} // namespace Service
} // namespace Service::Audio

View File

@@ -9,8 +9,7 @@
#include "core/hle/service/audio/audren_u.h"
#include "core/hle/service/audio/codecctl.h"
namespace Service {
namespace Audio {
namespace Service::Audio {
void InstallInterfaces(SM::ServiceManager& service_manager) {
std::make_shared<AudOutU>()->InstallAsService(service_manager);
@@ -20,5 +19,4 @@ void InstallInterfaces(SM::ServiceManager& service_manager) {
std::make_shared<CodecCtl>()->InstallAsService(service_manager);
}
} // namespace Audio
} // namespace Service
} // namespace Service::Audio

View File

@@ -6,11 +6,9 @@
#include "core/hle/service/service.h"
namespace Service {
namespace Audio {
namespace Service::Audio {
/// Registers all Audio services with the specified service manager.
void InstallInterfaces(SM::ServiceManager& service_manager);
} // namespace Audio
} // namespace Service
} // namespace Service::Audio

View File

@@ -10,8 +10,7 @@
#include "core/hle/kernel/hle_ipc.h"
#include "core/hle/service/audio/audout_u.h"
namespace Service {
namespace Audio {
namespace Service::Audio {
/// Switch sample rate frequency
constexpr u32 sample_rate{48000};
@@ -25,15 +24,18 @@ class IAudioOut final : public ServiceFramework<IAudioOut> {
public:
IAudioOut() : ServiceFramework("IAudioOut"), audio_out_state(AudioState::Stopped) {
static const FunctionInfo functions[] = {
{0x0, &IAudioOut::GetAudioOutState, "GetAudioOutState"},
{0x1, &IAudioOut::StartAudioOut, "StartAudioOut"},
{0x2, &IAudioOut::StopAudioOut, "StopAudioOut"},
{0x3, &IAudioOut::AppendAudioOutBuffer_1, "AppendAudioOutBuffer_1"},
{0x4, &IAudioOut::RegisterBufferEvent, "RegisterBufferEvent"},
{0x5, &IAudioOut::GetReleasedAudioOutBuffer_1, "GetReleasedAudioOutBuffer_1"},
{0x6, nullptr, "ContainsAudioOutBuffer"},
{0x7, nullptr, "AppendAudioOutBuffer_2"},
{0x8, nullptr, "GetReleasedAudioOutBuffer_2"},
{0, &IAudioOut::GetAudioOutState, "GetAudioOutState"},
{1, &IAudioOut::StartAudioOut, "StartAudioOut"},
{2, &IAudioOut::StopAudioOut, "StopAudioOut"},
{3, &IAudioOut::AppendAudioOutBuffer, "AppendAudioOutBuffer"},
{4, &IAudioOut::RegisterBufferEvent, "RegisterBufferEvent"},
{5, &IAudioOut::GetReleasedAudioOutBuffer, "GetReleasedAudioOutBuffer"},
{6, nullptr, "ContainsAudioOutBuffer"},
{7, nullptr, "AppendAudioOutBufferAuto"},
{8, nullptr, "GetReleasedAudioOutBufferAuto"},
{9, nullptr, "GetAudioOutBufferCount"},
{10, nullptr, "GetAudioOutPlayedSampleCount"},
{11, nullptr, "FlushAudioOutBuffers"},
};
RegisterHandlers(functions);
@@ -58,14 +60,14 @@ public:
private:
void GetAudioOutState(Kernel::HLERequestContext& ctx) {
LOG_DEBUG(Service_Audio, "called");
NGLOG_DEBUG(Service_Audio, "called");
IPC::ResponseBuilder rb{ctx, 3};
rb.Push(RESULT_SUCCESS);
rb.Push(static_cast<u32>(audio_out_state));
}
void StartAudioOut(Kernel::HLERequestContext& ctx) {
LOG_WARNING(Service_Audio, "(STUBBED) called");
NGLOG_WARNING(Service_Audio, "(STUBBED) called");
// Start audio
audio_out_state = AudioState::Started;
@@ -75,7 +77,7 @@ private:
}
void StopAudioOut(Kernel::HLERequestContext& ctx) {
LOG_WARNING(Service_Audio, "(STUBBED) called");
NGLOG_WARNING(Service_Audio, "(STUBBED) called");
// Stop audio
audio_out_state = AudioState::Stopped;
@@ -87,15 +89,15 @@ private:
}
void RegisterBufferEvent(Kernel::HLERequestContext& ctx) {
LOG_WARNING(Service_Audio, "(STUBBED) called");
NGLOG_WARNING(Service_Audio, "(STUBBED) called");
IPC::ResponseBuilder rb{ctx, 2, 1};
rb.Push(RESULT_SUCCESS);
rb.PushCopyObjects(buffer_event);
}
void AppendAudioOutBuffer_1(Kernel::HLERequestContext& ctx) {
LOG_WARNING(Service_Audio, "(STUBBED) called");
void AppendAudioOutBuffer(Kernel::HLERequestContext& ctx) {
NGLOG_WARNING(Service_Audio, "(STUBBED) called");
IPC::RequestParser rp{ctx};
const u64 key{rp.Pop<u64>()};
@@ -105,8 +107,8 @@ private:
rb.Push(RESULT_SUCCESS);
}
void GetReleasedAudioOutBuffer_1(Kernel::HLERequestContext& ctx) {
LOG_WARNING(Service_Audio, "(STUBBED) called");
void GetReleasedAudioOutBuffer(Kernel::HLERequestContext& ctx) {
NGLOG_WARNING(Service_Audio, "(STUBBED) called");
// TODO(st4rk): This is how libtransistor currently implements the
// GetReleasedAudioOutBuffer, it should return the key (a VAddr) to the app and this address
@@ -162,7 +164,7 @@ private:
};
void AudOutU::ListAudioOuts(Kernel::HLERequestContext& ctx) {
LOG_WARNING(Service_Audio, "(STUBBED) called");
NGLOG_WARNING(Service_Audio, "(STUBBED) called");
IPC::RequestParser rp{ctx};
const std::string audio_interface = "AudioInterface";
@@ -178,7 +180,7 @@ void AudOutU::ListAudioOuts(Kernel::HLERequestContext& ctx) {
}
void AudOutU::OpenAudioOut(Kernel::HLERequestContext& ctx) {
LOG_WARNING(Service_Audio, "(STUBBED) called");
NGLOG_WARNING(Service_Audio, "(STUBBED) called");
if (!audio_out_interface) {
audio_out_interface = std::make_shared<IAudioOut>();
@@ -196,10 +198,9 @@ void AudOutU::OpenAudioOut(Kernel::HLERequestContext& ctx) {
AudOutU::AudOutU() : ServiceFramework("audout:u") {
static const FunctionInfo functions[] = {{0x00000000, &AudOutU::ListAudioOuts, "ListAudioOuts"},
{0x00000001, &AudOutU::OpenAudioOut, "OpenAudioOut"},
{0x00000002, nullptr, "Unknown2"},
{0x00000003, nullptr, "Unknown3"}};
{0x00000002, nullptr, "ListAudioOutsAuto"},
{0x00000003, nullptr, "OpenAudioOutAuto"}};
RegisterHandlers(functions);
}
} // namespace Audio
} // namespace Service
} // namespace Service::Audio

View File

@@ -10,8 +10,7 @@ namespace Kernel {
class HLERequestContext;
}
namespace Service {
namespace Audio {
namespace Service::Audio {
class IAudioOut;
@@ -37,5 +36,4 @@ private:
};
};
} // namespace Audio
} // namespace Service
} // namespace Service::Audio

View File

@@ -7,20 +7,21 @@
#include "core/hle/kernel/hle_ipc.h"
#include "core/hle/service/audio/audrec_u.h"
namespace Service {
namespace Audio {
namespace Service::Audio {
class IFinalOutputRecorder final : public ServiceFramework<IFinalOutputRecorder> {
public:
IFinalOutputRecorder() : ServiceFramework("IFinalOutputRecorder") {
static const FunctionInfo functions[] = {
{0x0, nullptr, "GetFinalOutputRecorderState"},
{0x1, nullptr, "StartFinalOutputRecorder"},
{0x2, nullptr, "StopFinalOutputRecorder"},
{0x3, nullptr, "AppendFinalOutputRecorderBuffer"},
{0x4, nullptr, "RegisterBufferEvent"},
{0x5, nullptr, "GetReleasedFinalOutputRecorderBuffer"},
{0x6, nullptr, "ContainsFinalOutputRecorderBuffer"},
{0, nullptr, "GetFinalOutputRecorderState"},
{1, nullptr, "StartFinalOutputRecorder"},
{2, nullptr, "StopFinalOutputRecorder"},
{3, nullptr, "AppendFinalOutputRecorderBuffer"},
{4, nullptr, "RegisterBufferEvent"},
{5, nullptr, "GetReleasedFinalOutputRecorderBuffer"},
{6, nullptr, "ContainsFinalOutputRecorderBuffer"},
{8, nullptr, "AppendFinalOutputRecorderBufferAuto"},
{9, nullptr, "GetReleasedFinalOutputRecorderBufferAuto"},
};
RegisterHandlers(functions);
}
@@ -34,5 +35,4 @@ AudRecU::AudRecU() : ServiceFramework("audrec:u") {
RegisterHandlers(functions);
}
} // namespace Audio
} // namespace Service
} // namespace Service::Audio

View File

@@ -10,8 +10,7 @@ namespace Kernel {
class HLERequestContext;
}
namespace Service {
namespace Audio {
namespace Service::Audio {
class AudRecU final : public ServiceFramework<AudRecU> {
public:
@@ -19,5 +18,4 @@ public:
~AudRecU() = default;
};
} // namespace Audio
} // namespace Service
} // namespace Service::Audio

View File

@@ -9,8 +9,7 @@
#include "core/hle/kernel/hle_ipc.h"
#include "core/hle/service/audio/audren_u.h"
namespace Service {
namespace Audio {
namespace Service::Audio {
/// TODO(bunnei): Find a proper value for the audio_ticks
constexpr u64 audio_ticks{static_cast<u64>(BASE_CLOCK_RATE / 200)};
@@ -19,16 +18,18 @@ class IAudioRenderer final : public ServiceFramework<IAudioRenderer> {
public:
IAudioRenderer() : ServiceFramework("IAudioRenderer") {
static const FunctionInfo functions[] = {
{0x0, nullptr, "GetAudioRendererSampleRate"},
{0x1, nullptr, "GetAudioRendererSampleCount"},
{0x2, nullptr, "GetAudioRendererMixBufferCount"},
{0x3, nullptr, "GetAudioRendererState"},
{0x4, &IAudioRenderer::RequestUpdateAudioRenderer, "RequestUpdateAudioRenderer"},
{0x5, &IAudioRenderer::StartAudioRenderer, "StartAudioRenderer"},
{0x6, &IAudioRenderer::StopAudioRenderer, "StopAudioRenderer"},
{0x7, &IAudioRenderer::QuerySystemEvent, "QuerySystemEvent"},
{0x8, nullptr, "SetAudioRendererRenderingTimeLimit"},
{0x9, nullptr, "GetAudioRendererRenderingTimeLimit"},
{0, nullptr, "GetAudioRendererSampleRate"},
{1, nullptr, "GetAudioRendererSampleCount"},
{2, nullptr, "GetAudioRendererMixBufferCount"},
{3, nullptr, "GetAudioRendererState"},
{4, &IAudioRenderer::RequestUpdateAudioRenderer, "RequestUpdateAudioRenderer"},
{5, &IAudioRenderer::StartAudioRenderer, "StartAudioRenderer"},
{6, &IAudioRenderer::StopAudioRenderer, "StopAudioRenderer"},
{7, &IAudioRenderer::QuerySystemEvent, "QuerySystemEvent"},
{8, nullptr, "SetAudioRendererRenderingTimeLimit"},
{9, nullptr, "GetAudioRendererRenderingTimeLimit"},
{10, nullptr, "RequestUpdateAudioRendererAuto"},
{11, nullptr, "ExecuteAudioRendererRendering"},
};
RegisterHandlers(functions);
@@ -55,7 +56,7 @@ private:
}
void RequestUpdateAudioRenderer(Kernel::HLERequestContext& ctx) {
LOG_DEBUG(Service_Audio, "%s", ctx.Description().c_str());
NGLOG_DEBUG(Service_Audio, "{}", ctx.Description());
AudioRendererResponseData response_data{};
response_data.section_0_size =
@@ -78,7 +79,7 @@ private:
rb.Push(RESULT_SUCCESS);
LOG_WARNING(Service_Audio, "(STUBBED) called");
NGLOG_WARNING(Service_Audio, "(STUBBED) called");
}
void StartAudioRenderer(Kernel::HLERequestContext& ctx) {
@@ -86,7 +87,7 @@ private:
rb.Push(RESULT_SUCCESS);
LOG_WARNING(Service_Audio, "(STUBBED) called");
NGLOG_WARNING(Service_Audio, "(STUBBED) called");
}
void StopAudioRenderer(Kernel::HLERequestContext& ctx) {
@@ -94,7 +95,7 @@ private:
rb.Push(RESULT_SUCCESS);
LOG_WARNING(Service_Audio, "(STUBBED) called");
NGLOG_WARNING(Service_Audio, "(STUBBED) called");
}
void QuerySystemEvent(Kernel::HLERequestContext& ctx) {
@@ -104,7 +105,7 @@ private:
rb.Push(RESULT_SUCCESS);
rb.PushCopyObjects(system_event);
LOG_WARNING(Service_Audio, "(STUBBED) called");
NGLOG_WARNING(Service_Audio, "(STUBBED) called");
}
struct AudioRendererStateEntry {
@@ -175,7 +176,7 @@ public:
private:
void ListAudioDeviceName(Kernel::HLERequestContext& ctx) {
LOG_WARNING(Service_Audio, "(STUBBED) called");
NGLOG_WARNING(Service_Audio, "(STUBBED) called");
IPC::RequestParser rp{ctx};
const std::string audio_interface = "AudioInterface";
@@ -187,7 +188,7 @@ private:
}
void SetAudioDeviceOutputVolume(Kernel::HLERequestContext& ctx) {
LOG_WARNING(Service_Audio, "(STUBBED) called");
NGLOG_WARNING(Service_Audio, "(STUBBED) called");
IPC::RequestParser rp{ctx};
f32 volume = static_cast<f32>(rp.Pop<u32>());
@@ -200,7 +201,7 @@ private:
}
void GetActiveAudioDeviceName(Kernel::HLERequestContext& ctx) {
LOG_WARNING(Service_Audio, "(STUBBED) called");
NGLOG_WARNING(Service_Audio, "(STUBBED) called");
IPC::RequestParser rp{ctx};
const std::string audio_interface = "AudioDevice";
@@ -212,7 +213,7 @@ private:
}
void QueryAudioDeviceSystemEvent(Kernel::HLERequestContext& ctx) {
LOG_WARNING(Service_Audio, "(STUBBED) called");
NGLOG_WARNING(Service_Audio, "(STUBBED) called");
buffer_event->Signal();
@@ -222,7 +223,7 @@ private:
}
void GetActiveChannelCount(Kernel::HLERequestContext& ctx) {
LOG_WARNING(Service_Audio, "(STUBBED) called");
NGLOG_WARNING(Service_Audio, "(STUBBED) called");
IPC::ResponseBuilder rb{ctx, 3};
rb.Push(RESULT_SUCCESS);
rb.Push<u32>(1);
@@ -237,6 +238,8 @@ AudRenU::AudRenU() : ServiceFramework("audren:u") {
{0, &AudRenU::OpenAudioRenderer, "OpenAudioRenderer"},
{1, &AudRenU::GetAudioRendererWorkBufferSize, "GetAudioRendererWorkBufferSize"},
{2, &AudRenU::GetAudioDevice, "GetAudioDevice"},
{3, nullptr, "OpenAudioRendererAuto"},
{4, nullptr, "GetAudioDeviceServiceWithRevisionInfo"},
};
RegisterHandlers(functions);
}
@@ -247,7 +250,7 @@ void AudRenU::OpenAudioRenderer(Kernel::HLERequestContext& ctx) {
rb.Push(RESULT_SUCCESS);
rb.PushIpcInterface<Audio::IAudioRenderer>();
LOG_DEBUG(Service_Audio, "called");
NGLOG_DEBUG(Service_Audio, "called");
}
void AudRenU::GetAudioRendererWorkBufferSize(Kernel::HLERequestContext& ctx) {
@@ -256,7 +259,7 @@ void AudRenU::GetAudioRendererWorkBufferSize(Kernel::HLERequestContext& ctx) {
rb.Push(RESULT_SUCCESS);
rb.Push<u64>(0x400);
LOG_WARNING(Service_Audio, "(STUBBED) called");
NGLOG_WARNING(Service_Audio, "(STUBBED) called");
}
void AudRenU::GetAudioDevice(Kernel::HLERequestContext& ctx) {
@@ -265,8 +268,7 @@ void AudRenU::GetAudioDevice(Kernel::HLERequestContext& ctx) {
rb.Push(RESULT_SUCCESS);
rb.PushIpcInterface<Audio::IAudioDevice>();
LOG_DEBUG(Service_Audio, "called");
NGLOG_DEBUG(Service_Audio, "called");
}
} // namespace Audio
} // namespace Service
} // namespace Service::Audio

View File

@@ -10,8 +10,7 @@ namespace Kernel {
class HLERequestContext;
}
namespace Service {
namespace Audio {
namespace Service::Audio {
class AudRenU final : public ServiceFramework<AudRenU> {
public:
@@ -24,5 +23,4 @@ private:
void GetAudioDevice(Kernel::HLERequestContext& ctx);
};
} // namespace Audio
} // namespace Service
} // namespace Service::Audio

View File

@@ -7,8 +7,7 @@
#include "core/hle/kernel/hle_ipc.h"
#include "core/hle/service/audio/codecctl.h"
namespace Service {
namespace Audio {
namespace Service::Audio {
CodecCtl::CodecCtl() : ServiceFramework("codecctl") {
static const FunctionInfo functions[] = {
@@ -22,12 +21,11 @@ CodecCtl::CodecCtl() : ServiceFramework("codecctl") {
{0x00000007, nullptr, "SetCodecActiveTarget"},
{0x00000008, nullptr, "Unknown"},
{0x00000009, nullptr, "BindCodecHeadphoneMicJackInterrupt"},
{0x0000000A, nullptr, "IsCodecHeadphoneMicJackInserted"},
{0x0000000B, nullptr, "ClearCodecHeadphoneMicJackInterrupt"},
{0x0000000C, nullptr, "IsCodecDeviceRequested"},
{0x00000010, nullptr, "IsCodecHeadphoneMicJackInserted"},
{0x00000011, nullptr, "ClearCodecHeadphoneMicJackInterrupt"},
{0x00000012, nullptr, "IsCodecDeviceRequested"},
};
RegisterHandlers(functions);
}
} // namespace Audio
} // namespace Service
} // namespace Service::Audio

View File

@@ -10,8 +10,7 @@ namespace Kernel {
class HLERequestContext;
}
namespace Service {
namespace Audio {
namespace Service::Audio {
class CodecCtl final : public ServiceFramework<CodecCtl> {
public:
@@ -19,5 +18,4 @@ public:
~CodecCtl() = default;
};
} // namespace Audio
} // namespace Service
} // namespace Service::Audio

View File

@@ -8,8 +8,7 @@
#include "core/hle/service/fatal/fatal_p.h"
#include "core/hle/service/fatal/fatal_u.h"
namespace Service {
namespace Fatal {
namespace Service::Fatal {
Module::Interface::Interface(std::shared_ptr<Module> module, const char* name)
: ServiceFramework(name), module(std::move(module)) {}
@@ -17,13 +16,13 @@ Module::Interface::Interface(std::shared_ptr<Module> module, const char* name)
void Module::Interface::FatalSimple(Kernel::HLERequestContext& ctx) {
IPC::RequestParser rp(ctx);
u32 error_code = rp.Pop<u32>();
LOG_WARNING(Service_Fatal, "(STUBBED) called, error_code=0x%X", error_code);
NGLOG_WARNING(Service_Fatal, "(STUBBED) called, error_code={:#X}", error_code);
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS);
}
void Module::Interface::TransitionToFatalError(Kernel::HLERequestContext& ctx) {
LOG_WARNING(Service_Fatal, "(STUBBED) called");
NGLOG_WARNING(Service_Fatal, "(STUBBED) called");
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS);
}
@@ -34,5 +33,4 @@ void InstallInterfaces(SM::ServiceManager& service_manager) {
std::make_shared<Fatal_U>(module)->InstallAsService(service_manager);
}
} // namespace Fatal
} // namespace Service
} // namespace Service::Fatal

View File

@@ -6,8 +6,7 @@
#include "core/hle/service/service.h"
namespace Service {
namespace Fatal {
namespace Service::Fatal {
class Module final {
public:
@@ -25,5 +24,4 @@ public:
void InstallInterfaces(SM::ServiceManager& service_manager);
} // namespace Fatal
} // namespace Service
} // namespace Service::Fatal

View File

@@ -4,11 +4,9 @@
#include "core/hle/service/fatal/fatal_p.h"
namespace Service {
namespace Fatal {
namespace Service::Fatal {
Fatal_P::Fatal_P(std::shared_ptr<Module> module)
: Module::Interface(std::move(module), "fatal:p") {}
} // namespace Fatal
} // namespace Service
} // namespace Service::Fatal

View File

@@ -6,13 +6,11 @@
#include "core/hle/service/fatal/fatal.h"
namespace Service {
namespace Fatal {
namespace Service::Fatal {
class Fatal_P final : public Module::Interface {
public:
explicit Fatal_P(std::shared_ptr<Module> module);
};
} // namespace Fatal
} // namespace Service
} // namespace Service::Fatal

View File

@@ -4,8 +4,7 @@
#include "core/hle/service/fatal/fatal_u.h"
namespace Service {
namespace Fatal {
namespace Service::Fatal {
Fatal_U::Fatal_U(std::shared_ptr<Module> module) : Module::Interface(std::move(module), "fatal:u") {
static const FunctionInfo functions[] = {
@@ -15,5 +14,4 @@ Fatal_U::Fatal_U(std::shared_ptr<Module> module) : Module::Interface(std::move(m
RegisterHandlers(functions);
}
} // namespace Fatal
} // namespace Service
} // namespace Service::Fatal

View File

@@ -6,13 +6,11 @@
#include "core/hle/service/fatal/fatal.h"
namespace Service {
namespace Fatal {
namespace Service::Fatal {
class Fatal_U final : public Module::Interface {
public:
explicit Fatal_U(std::shared_ptr<Module> module);
};
} // namespace Fatal
} // namespace Service
} // namespace Service::Fatal

View File

@@ -10,8 +10,7 @@
#include "core/hle/service/filesystem/filesystem.h"
#include "core/hle/service/filesystem/fsp_srv.h"
namespace Service {
namespace FileSystem {
namespace Service::FileSystem {
/**
* Map of registered file systems, identified by type. Once an file system is registered here, it
@@ -26,14 +25,14 @@ ResultCode RegisterFileSystem(std::unique_ptr<FileSys::FileSystemFactory>&& fact
ASSERT_MSG(inserted, "Tried to register more than one system with same id code");
auto& filesystem = result.first->second;
LOG_DEBUG(Service_FS, "Registered file system %s with id code 0x%08X",
filesystem->GetName().c_str(), static_cast<u32>(type));
NGLOG_DEBUG(Service_FS, "Registered file system {} with id code {:#010X}",
filesystem->GetName(), static_cast<u32>(type));
return RESULT_SUCCESS;
}
ResultVal<std::unique_ptr<FileSys::FileSystemBackend>> OpenFileSystem(Type type,
FileSys::Path& path) {
LOG_TRACE(Service_FS, "Opening FileSystem with type=%d", type);
NGLOG_TRACE(Service_FS, "Opening FileSystem with type={}", static_cast<u32>(type));
auto itr = filesystem_map.find(type);
if (itr == filesystem_map.end()) {
@@ -45,7 +44,7 @@ ResultVal<std::unique_ptr<FileSys::FileSystemBackend>> OpenFileSystem(Type type,
}
ResultCode FormatFileSystem(Type type) {
LOG_TRACE(Service_FS, "Formatting FileSystem with type=%d", type);
NGLOG_TRACE(Service_FS, "Formatting FileSystem with type={}", static_cast<u32>(type));
auto itr = filesystem_map.find(type);
if (itr == filesystem_map.end()) {
@@ -75,5 +74,4 @@ void InstallInterfaces(SM::ServiceManager& service_manager) {
std::make_shared<FSP_SRV>()->InstallAsService(service_manager);
}
} // namespace FileSystem
} // namespace Service
} // namespace Service::FileSystem

View File

@@ -14,8 +14,7 @@
#include "core/hle/service/filesystem/filesystem.h"
#include "core/hle/service/filesystem/fsp_srv.h"
namespace Service {
namespace FileSystem {
namespace Service::FileSystem {
class IStorage final : public ServiceFramework<IStorage> {
public:
@@ -23,7 +22,7 @@ public:
: ServiceFramework("IStorage"), backend(std::move(backend)) {
static const FunctionInfo functions[] = {
{0, &IStorage::Read, "Read"}, {1, nullptr, "Write"}, {2, nullptr, "Flush"},
{3, nullptr, "SetSize"}, {4, nullptr, "GetSize"},
{3, nullptr, "SetSize"}, {4, nullptr, "GetSize"}, {5, nullptr, "OperateRange"},
};
RegisterHandlers(functions);
}
@@ -36,7 +35,7 @@ private:
const s64 offset = rp.Pop<s64>();
const s64 length = rp.Pop<s64>();
LOG_DEBUG(Service_FS, "called, offset=0x%ld, length=0x%ld", offset, length);
NGLOG_DEBUG(Service_FS, "called, offset={:#X}, length={}", offset, length);
// Error checking
if (length < 0) {
@@ -72,8 +71,9 @@ public:
explicit IFile(std::unique_ptr<FileSys::StorageBackend>&& backend)
: ServiceFramework("IFile"), backend(std::move(backend)) {
static const FunctionInfo functions[] = {
{0, &IFile::Read, "Read"}, {1, &IFile::Write, "Write"}, {2, nullptr, "Flush"},
{3, &IFile::SetSize, "SetSize"}, {4, &IFile::GetSize, "GetSize"},
{0, &IFile::Read, "Read"}, {1, &IFile::Write, "Write"},
{2, &IFile::Flush, "Flush"}, {3, &IFile::SetSize, "SetSize"},
{4, &IFile::GetSize, "GetSize"}, {5, nullptr, "OperateRange"},
};
RegisterHandlers(functions);
}
@@ -87,7 +87,7 @@ private:
const s64 offset = rp.Pop<s64>();
const s64 length = rp.Pop<s64>();
LOG_DEBUG(Service_FS, "called, offset=0x%ld, length=0x%ld", offset, length);
NGLOG_DEBUG(Service_FS, "called, offset={:#X}, length={}", offset, length);
// Error checking
if (length < 0) {
@@ -124,7 +124,7 @@ private:
const s64 offset = rp.Pop<s64>();
const s64 length = rp.Pop<s64>();
LOG_DEBUG(Service_FS, "called, offset=0x%ld, length=0x%ld", offset, length);
NGLOG_DEBUG(Service_FS, "called, offset={:#X}, length={}", offset, length);
// Error checking
if (length < 0) {
@@ -151,11 +151,19 @@ private:
rb.Push(RESULT_SUCCESS);
}
void Flush(Kernel::HLERequestContext& ctx) {
NGLOG_DEBUG(Service_FS, "called");
backend->Flush();
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS);
}
void SetSize(Kernel::HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
const u64 size = rp.Pop<u64>();
backend->SetSize(size);
LOG_DEBUG(Service_FS, "called, size=%" PRIu64, size);
NGLOG_DEBUG(Service_FS, "called, size={}", size);
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS);
@@ -163,7 +171,7 @@ private:
void GetSize(Kernel::HLERequestContext& ctx) {
const u64 size = backend->GetSize();
LOG_DEBUG(Service_FS, "called, size=%" PRIu64, size);
NGLOG_DEBUG(Service_FS, "called, size={}", size);
IPC::ResponseBuilder rb{ctx, 4};
rb.Push(RESULT_SUCCESS);
@@ -189,7 +197,7 @@ private:
IPC::RequestParser rp{ctx};
const u64 unk = rp.Pop<u64>();
LOG_DEBUG(Service_FS, "called, unk=0x%llx", unk);
NGLOG_DEBUG(Service_FS, "called, unk={:#X}", unk);
// Calculate how many entries we can fit in the output buffer
u64 count_entries = ctx.GetWriteBufferSize() / sizeof(FileSys::Entry);
@@ -211,7 +219,7 @@ private:
}
void GetEntryCount(Kernel::HLERequestContext& ctx) {
LOG_DEBUG(Service_FS, "called");
NGLOG_DEBUG(Service_FS, "called");
u64 count = backend->GetEntryCount();
@@ -227,11 +235,21 @@ public:
: ServiceFramework("IFileSystem"), backend(std::move(backend)) {
static const FunctionInfo functions[] = {
{0, &IFileSystem::CreateFile, "CreateFile"},
{1, &IFileSystem::DeleteFile, "DeleteFile"},
{2, &IFileSystem::CreateDirectory, "CreateDirectory"},
{3, nullptr, "DeleteDirectory"},
{4, nullptr, "DeleteDirectoryRecursively"},
{5, &IFileSystem::RenameFile, "RenameFile"},
{6, nullptr, "RenameDirectory"},
{7, &IFileSystem::GetEntryType, "GetEntryType"},
{8, &IFileSystem::OpenFile, "OpenFile"},
{9, &IFileSystem::OpenDirectory, "OpenDirectory"},
{10, &IFileSystem::Commit, "Commit"},
{11, nullptr, "GetFreeSpaceSize"},
{12, nullptr, "GetTotalSpaceSize"},
{13, nullptr, "CleanDirectoryRecursively"},
{14, nullptr, "GetFileTimeStampRaw"},
{15, nullptr, "QueryEntry"},
};
RegisterHandlers(functions);
}
@@ -247,13 +265,26 @@ public:
u64 mode = rp.Pop<u64>();
u32 size = rp.Pop<u32>();
LOG_DEBUG(Service_FS, "called file %s mode 0x%" PRIX64 " size 0x%08X", name.c_str(), mode,
size);
NGLOG_DEBUG(Service_FS, "called file {} mode {:#X} size {:#010X}", name, mode, size);
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(backend->CreateFile(name, size));
}
void DeleteFile(Kernel::HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
auto file_buffer = ctx.ReadBuffer();
auto end = std::find(file_buffer.begin(), file_buffer.end(), '\0');
std::string name(file_buffer.begin(), end);
NGLOG_DEBUG(Service_FS, "called file {}", name);
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(backend->DeleteFile(name));
}
void CreateDirectory(Kernel::HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
@@ -262,12 +293,32 @@ public:
std::string name(file_buffer.begin(), end);
LOG_DEBUG(Service_FS, "called directory %s", name.c_str());
NGLOG_DEBUG(Service_FS, "called directory {}", name);
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(backend->CreateDirectory(name));
}
void RenameFile(Kernel::HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
std::vector<u8> buffer;
buffer.resize(ctx.BufferDescriptorX()[0].Size());
Memory::ReadBlock(ctx.BufferDescriptorX()[0].Address(), buffer.data(), buffer.size());
auto end = std::find(buffer.begin(), buffer.end(), '\0');
std::string src_name(buffer.begin(), end);
buffer.resize(ctx.BufferDescriptorX()[1].Size());
Memory::ReadBlock(ctx.BufferDescriptorX()[1].Address(), buffer.data(), buffer.size());
end = std::find(buffer.begin(), buffer.end(), '\0');
std::string dst_name(buffer.begin(), end);
NGLOG_DEBUG(Service_FS, "called file '{}' to file '{}'", src_name, dst_name);
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(backend->RenameFile(src_name, dst_name));
}
void OpenFile(Kernel::HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
@@ -278,7 +329,7 @@ public:
auto mode = static_cast<FileSys::Mode>(rp.Pop<u32>());
LOG_DEBUG(Service_FS, "called file %s mode %u", name.c_str(), static_cast<u32>(mode));
NGLOG_DEBUG(Service_FS, "called file {} mode {}", name, static_cast<u32>(mode));
auto result = backend->OpenFile(name, mode);
if (result.Failed()) {
@@ -305,7 +356,7 @@ public:
// TODO(Subv): Implement this filter.
u32 filter_flags = rp.Pop<u32>();
LOG_DEBUG(Service_FS, "called directory %s filter %u", name.c_str(), filter_flags);
NGLOG_DEBUG(Service_FS, "called directory {} filter {}", name, filter_flags);
auto result = backend->OpenDirectory(name);
if (result.Failed()) {
@@ -329,7 +380,7 @@ public:
std::string name(file_buffer.begin(), end);
LOG_DEBUG(Service_FS, "called file %s", name.c_str());
NGLOG_DEBUG(Service_FS, "called file {}", name);
auto result = backend->GetEntryType(name);
if (result.Failed()) {
@@ -344,7 +395,7 @@ public:
}
void Commit(Kernel::HLERequestContext& ctx) {
LOG_WARNING(Service_FS, "(STUBBED) called");
NGLOG_WARNING(Service_FS, "(STUBBED) called");
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS);
@@ -356,14 +407,94 @@ private:
FSP_SRV::FSP_SRV() : ServiceFramework("fsp-srv") {
static const FunctionInfo functions[] = {
{0, nullptr, "MountContent"},
{1, &FSP_SRV::Initialize, "Initialize"},
{2, nullptr, "OpenDataFileSystemByCurrentProcess"},
{7, nullptr, "OpenFileSystemWithPatch"},
{8, nullptr, "OpenFileSystemWithId"},
{9, nullptr, "OpenDataFileSystemByApplicationId"},
{11, nullptr, "OpenBisFileSystem"},
{12, nullptr, "OpenBisStorage"},
{13, nullptr, "InvalidateBisCache"},
{17, nullptr, "OpenHostFileSystem"},
{18, &FSP_SRV::MountSdCard, "MountSdCard"},
{19, nullptr, "FormatSdCardFileSystem"},
{21, nullptr, "DeleteSaveDataFileSystem"},
{22, &FSP_SRV::CreateSaveData, "CreateSaveData"},
{23, nullptr, "CreateSaveDataFileSystemBySystemSaveDataId"},
{24, nullptr, "RegisterSaveDataFileSystemAtomicDeletion"},
{25, nullptr, "DeleteSaveDataFileSystemBySaveDataSpaceId"},
{26, nullptr, "FormatSdCardDryRun"},
{27, nullptr, "IsExFatSupported"},
{28, nullptr, "DeleteSaveDataFileSystemBySaveDataAttribute"},
{30, nullptr, "OpenGameCardStorage"},
{31, nullptr, "OpenGameCardFileSystem"},
{32, nullptr, "ExtendSaveDataFileSystem"},
{33, nullptr, "DeleteCacheStorage"},
{34, nullptr, "GetCacheStorageSize"},
{51, &FSP_SRV::MountSaveData, "MountSaveData"},
{52, nullptr, "OpenSaveDataFileSystemBySystemSaveDataId"},
{53, nullptr, "OpenReadOnlySaveDataFileSystem"},
{57, nullptr, "ReadSaveDataFileSystemExtraDataBySaveDataSpaceId"},
{58, nullptr, "ReadSaveDataFileSystemExtraData"},
{59, nullptr, "WriteSaveDataFileSystemExtraData"},
{60, nullptr, "OpenSaveDataInfoReader"},
{61, nullptr, "OpenSaveDataInfoReaderBySaveDataSpaceId"},
{62, nullptr, "OpenCacheStorageList"},
{64, nullptr, "OpenSaveDataInternalStorageFileSystem"},
{65, nullptr, "UpdateSaveDataMacForDebug"},
{66, nullptr, "WriteSaveDataFileSystemExtraData2"},
{80, nullptr, "OpenSaveDataMetaFile"},
{81, nullptr, "OpenSaveDataTransferManager"},
{82, nullptr, "OpenSaveDataTransferManagerVersion2"},
{100, nullptr, "OpenImageDirectoryFileSystem"},
{110, nullptr, "OpenContentStorageFileSystem"},
{200, &FSP_SRV::OpenDataStorageByCurrentProcess, "OpenDataStorageByCurrentProcess"},
{201, nullptr, "OpenDataStorageByProgramId"},
{202, nullptr, "OpenDataStorageByDataId"},
{203, &FSP_SRV::OpenRomStorage, "OpenRomStorage"},
{400, nullptr, "OpenDeviceOperator"},
{500, nullptr, "OpenSdCardDetectionEventNotifier"},
{501, nullptr, "OpenGameCardDetectionEventNotifier"},
{510, nullptr, "OpenSystemDataUpdateEventNotifier"},
{511, nullptr, "NotifySystemDataUpdateEvent"},
{600, nullptr, "SetCurrentPosixTime"},
{601, nullptr, "QuerySaveDataTotalSize"},
{602, nullptr, "VerifySaveDataFileSystem"},
{603, nullptr, "CorruptSaveDataFileSystem"},
{604, nullptr, "CreatePaddingFile"},
{605, nullptr, "DeleteAllPaddingFiles"},
{606, nullptr, "GetRightsId"},
{607, nullptr, "RegisterExternalKey"},
{608, nullptr, "UnregisterAllExternalKey"},
{609, nullptr, "GetRightsIdByPath"},
{610, nullptr, "GetRightsIdAndKeyGenerationByPath"},
{611, nullptr, "SetCurrentPosixTimeWithTimeDifference"},
{612, nullptr, "GetFreeSpaceSizeForSaveData"},
{613, nullptr, "VerifySaveDataFileSystemBySaveDataSpaceId"},
{614, nullptr, "CorruptSaveDataFileSystemBySaveDataSpaceId"},
{615, nullptr, "QuerySaveDataInternalStorageTotalSize"},
{620, nullptr, "SetSdCardEncryptionSeed"},
{630, nullptr, "SetSdCardAccessibility"},
{631, nullptr, "IsSdCardAccessible"},
{640, nullptr, "IsSignedSystemPartitionOnSdCardValid"},
{700, nullptr, "OpenAccessFailureResolver"},
{701, nullptr, "GetAccessFailureDetectionEvent"},
{702, nullptr, "IsAccessFailureDetected"},
{710, nullptr, "ResolveAccessFailure"},
{720, nullptr, "AbandonAccessFailure"},
{800, nullptr, "GetAndClearFileSystemProxyErrorInfo"},
{1000, nullptr, "SetBisRootForHost"},
{1001, nullptr, "SetSaveDataSize"},
{1002, nullptr, "SetSaveDataRootPath"},
{1003, nullptr, "DisableAutoSaveDataCreation"},
{1004, nullptr, "SetGlobalAccessLogMode"},
{1005, &FSP_SRV::GetGlobalAccessLogMode, "GetGlobalAccessLogMode"},
{1006, nullptr, "OutputAccessLogToSdCard"},
{1007, nullptr, "RegisterUpdatePartition"},
{1008, nullptr, "OpenRegisteredUpdatePartition"},
{1009, nullptr, "GetAndClearMemoryReportInfo"},
{1100, nullptr, "OverrideSaveDataTransferTokenSignVerificationKey"},
};
RegisterHandlers(functions);
}
@@ -380,14 +511,14 @@ void FSP_SRV::TryLoadRomFS() {
}
void FSP_SRV::Initialize(Kernel::HLERequestContext& ctx) {
LOG_WARNING(Service_FS, "(STUBBED) called");
NGLOG_WARNING(Service_FS, "(STUBBED) called");
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS);
}
void FSP_SRV::MountSdCard(Kernel::HLERequestContext& ctx) {
LOG_DEBUG(Service_FS, "called");
NGLOG_DEBUG(Service_FS, "called");
FileSys::Path unused;
auto filesystem = OpenFileSystem(Type::SDMC, unused).Unwrap();
@@ -404,14 +535,14 @@ void FSP_SRV::CreateSaveData(Kernel::HLERequestContext& ctx) {
auto save_create_struct = rp.PopRaw<std::array<u8, 0x40>>();
u128 uid = rp.PopRaw<u128>();
LOG_WARNING(Service_FS, "(STUBBED) called uid = %016" PRIX64 "%016" PRIX64, uid[1], uid[0]);
NGLOG_WARNING(Service_FS, "(STUBBED) called uid = {:016X}{:016X}", uid[1], uid[0]);
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS);
}
void FSP_SRV::MountSaveData(Kernel::HLERequestContext& ctx) {
LOG_WARNING(Service_FS, "(STUBBED) called");
NGLOG_WARNING(Service_FS, "(STUBBED) called");
FileSys::Path unused;
auto filesystem = OpenFileSystem(Type::SaveData, unused).Unwrap();
@@ -422,7 +553,7 @@ void FSP_SRV::MountSaveData(Kernel::HLERequestContext& ctx) {
}
void FSP_SRV::GetGlobalAccessLogMode(Kernel::HLERequestContext& ctx) {
LOG_WARNING(Service_FS, "(STUBBED) called");
NGLOG_WARNING(Service_FS, "(STUBBED) called");
IPC::ResponseBuilder rb{ctx, 3};
rb.Push(RESULT_SUCCESS);
@@ -430,12 +561,12 @@ void FSP_SRV::GetGlobalAccessLogMode(Kernel::HLERequestContext& ctx) {
}
void FSP_SRV::OpenDataStorageByCurrentProcess(Kernel::HLERequestContext& ctx) {
LOG_DEBUG(Service_FS, "called");
NGLOG_DEBUG(Service_FS, "called");
TryLoadRomFS();
if (!romfs) {
// TODO (bunnei): Find the right error code to use here
LOG_CRITICAL(Service_FS, "no file system interface available!");
NGLOG_CRITICAL(Service_FS, "no file system interface available!");
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(ResultCode(-1));
return;
@@ -444,7 +575,7 @@ void FSP_SRV::OpenDataStorageByCurrentProcess(Kernel::HLERequestContext& ctx) {
// Attempt to open a StorageBackend interface to the RomFS
auto storage = romfs->OpenFile({}, {});
if (storage.Failed()) {
LOG_CRITICAL(Service_FS, "no storage interface available!");
NGLOG_CRITICAL(Service_FS, "no storage interface available!");
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(storage.Code());
return;
@@ -456,9 +587,8 @@ void FSP_SRV::OpenDataStorageByCurrentProcess(Kernel::HLERequestContext& ctx) {
}
void FSP_SRV::OpenRomStorage(Kernel::HLERequestContext& ctx) {
LOG_WARNING(Service_FS, "(STUBBED) called, using OpenDataStorageByCurrentProcess");
NGLOG_WARNING(Service_FS, "(STUBBED) called, using OpenDataStorageByCurrentProcess");
OpenDataStorageByCurrentProcess(ctx);
}
} // namespace FileSystem
} // namespace Service
} // namespace Service::FileSystem

View File

@@ -11,8 +11,7 @@ namespace FileSys {
class FileSystemBackend;
}
namespace Service {
namespace FileSystem {
namespace Service::FileSystem {
class FSP_SRV final : public ServiceFramework<FSP_SRV> {
public:
@@ -33,5 +32,4 @@ private:
std::unique_ptr<FileSys::FileSystemBackend> romfs;
};
} // namespace FileSystem
} // namespace Service
} // namespace Service::FileSystem

View File

@@ -8,13 +8,12 @@
#include "core/hle/service/friend/friend_a.h"
#include "core/hle/service/friend/friend_u.h"
namespace Service {
namespace Friend {
namespace Service::Friend {
void Module::Interface::Unknown(Kernel::HLERequestContext& ctx) {
void Module::Interface::CreateFriendService(Kernel::HLERequestContext& ctx) {
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS);
LOG_WARNING(Service_Friend, "(STUBBED) called");
NGLOG_WARNING(Service_Friend, "(STUBBED) called");
}
Module::Interface::Interface(std::shared_ptr<Module> module, const char* name)
@@ -26,5 +25,4 @@ void InstallInterfaces(SM::ServiceManager& service_manager) {
std::make_shared<Friend_U>(module)->InstallAsService(service_manager);
}
} // namespace Friend
} // namespace Service
} // namespace Service::Friend

View File

@@ -6,8 +6,7 @@
#include "core/hle/service/service.h"
namespace Service {
namespace Friend {
namespace Service::Friend {
class Module final {
public:
@@ -15,7 +14,7 @@ public:
public:
Interface(std::shared_ptr<Module> module, const char* name);
void Unknown(Kernel::HLERequestContext& ctx);
void CreateFriendService(Kernel::HLERequestContext& ctx);
protected:
std::shared_ptr<Module> module;
@@ -25,5 +24,4 @@ public:
/// Registers all Friend services with the specified service manager.
void InstallInterfaces(SM::ServiceManager& service_manager);
} // namespace Friend
} // namespace Service
} // namespace Service::Friend

View File

@@ -4,16 +4,15 @@
#include "core/hle/service/friend/friend_a.h"
namespace Service {
namespace Friend {
namespace Service::Friend {
Friend_A::Friend_A(std::shared_ptr<Module> module)
: Module::Interface(std::move(module), "friend:a") {
static const FunctionInfo functions[] = {
{0, &Friend_A::Unknown, "Unknown"},
{0, &Friend_A::CreateFriendService, "CreateFriendService"},
{1, nullptr, "CreateNotificationService"},
};
RegisterHandlers(functions);
}
} // namespace Friend
} // namespace Service
} // namespace Service::Friend

View File

@@ -6,13 +6,11 @@
#include "core/hle/service/friend/friend.h"
namespace Service {
namespace Friend {
namespace Service::Friend {
class Friend_A final : public Module::Interface {
public:
explicit Friend_A(std::shared_ptr<Module> module);
};
} // namespace Friend
} // namespace Service
} // namespace Service::Friend

View File

@@ -4,16 +4,15 @@
#include "core/hle/service/friend/friend_u.h"
namespace Service {
namespace Friend {
namespace Service::Friend {
Friend_U::Friend_U(std::shared_ptr<Module> module)
: Module::Interface(std::move(module), "friend:u") {
static const FunctionInfo functions[] = {
{0, &Friend_U::Unknown, "Unknown"},
{0, &Friend_U::CreateFriendService, "CreateFriendService"},
{1, nullptr, "CreateNotificationService"},
};
RegisterHandlers(functions);
}
} // namespace Friend
} // namespace Service
} // namespace Service::Friend

View File

@@ -6,13 +6,11 @@
#include "core/hle/service/friend/friend.h"
namespace Service {
namespace Friend {
namespace Service::Friend {
class Friend_U final : public Module::Interface {
public:
explicit Friend_U(std::shared_ptr<Module> module);
};
} // namespace Friend
} // namespace Service
} // namespace Service::Friend

View File

@@ -14,8 +14,7 @@
#include "core/hle/service/hid/hid.h"
#include "core/hle/service/service.h"
namespace Service {
namespace HID {
namespace Service::HID {
// Updating period for each HID device.
// TODO(shinyquagsire23): These need better values.
@@ -54,7 +53,7 @@ private:
IPC::ResponseBuilder rb{ctx, 2, 1};
rb.Push(RESULT_SUCCESS);
rb.PushCopyObjects(shared_mem);
LOG_DEBUG(Service_HID, "called");
NGLOG_DEBUG(Service_HID, "called");
}
void LoadInputDevices() {
@@ -185,7 +184,7 @@ private:
void ActivateVibrationDevice(Kernel::HLERequestContext& ctx) {
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS);
LOG_WARNING(Service_HID, "(STUBBED) called");
NGLOG_WARNING(Service_HID, "(STUBBED) called");
}
};
@@ -198,25 +197,75 @@ public:
{11, &Hid::ActivateTouchScreen, "ActivateTouchScreen"},
{21, &Hid::ActivateMouse, "ActivateMouse"},
{31, &Hid::ActivateKeyboard, "ActivateKeyboard"},
{40, nullptr, "AcquireXpadIdEventHandle"},
{41, nullptr, "ReleaseXpadIdEventHandle"},
{51, nullptr, "ActivateXpad"},
{55, nullptr, "GetXpadIds"},
{56, nullptr, "ActivateJoyXpad"},
{58, nullptr, "GetJoyXpadLifoHandle"},
{59, nullptr, "GetJoyXpadIds"},
{60, nullptr, "ActivateSixAxisSensor"},
{61, nullptr, "DeactivateSixAxisSensor"},
{62, nullptr, "GetSixAxisSensorLifoHandle"},
{63, nullptr, "ActivateJoySixAxisSensor"},
{64, nullptr, "DeactivateJoySixAxisSensor"},
{65, nullptr, "GetJoySixAxisSensorLifoHandle"},
{66, &Hid::StartSixAxisSensor, "StartSixAxisSensor"},
{67, nullptr, "StopSixAxisSensor"},
{68, nullptr, "IsSixAxisSensorFusionEnabled"},
{69, nullptr, "EnableSixAxisSensorFusion"},
{70, nullptr, "SetSixAxisSensorFusionParameters"},
{71, nullptr, "GetSixAxisSensorFusionParameters"},
{72, nullptr, "ResetSixAxisSensorFusionParameters"},
{73, nullptr, "SetAccelerometerParameters"},
{74, nullptr, "GetAccelerometerParameters"},
{75, nullptr, "ResetAccelerometerParameters"},
{76, nullptr, "SetAccelerometerPlayMode"},
{77, nullptr, "GetAccelerometerPlayMode"},
{78, nullptr, "ResetAccelerometerPlayMode"},
{79, &Hid::SetGyroscopeZeroDriftMode, "SetGyroscopeZeroDriftMode"},
{80, nullptr, "GetGyroscopeZeroDriftMode"},
{81, nullptr, "ResetGyroscopeZeroDriftMode"},
{82, nullptr, "IsSixAxisSensorAtRest"},
{91, nullptr, "ActivateGesture"},
{100, &Hid::SetSupportedNpadStyleSet, "SetSupportedNpadStyleSet"},
{101, &Hid::GetSupportedNpadStyleSet, "GetSupportedNpadStyleSet"},
{102, &Hid::SetSupportedNpadIdType, "SetSupportedNpadIdType"},
{103, &Hid::ActivateNpad, "ActivateNpad"},
{104, nullptr, "DeactivateNpad"},
{106, &Hid::AcquireNpadStyleSetUpdateEventHandle,
"AcquireNpadStyleSetUpdateEventHandle"},
{107, nullptr, "DisconnectNpad"},
{108, &Hid::GetPlayerLedPattern, "GetPlayerLedPattern"},
{120, &Hid::SetNpadJoyHoldType, "SetNpadJoyHoldType"},
{121, &Hid::GetNpadJoyHoldType, "GetNpadJoyHoldType"},
{122, &Hid::SetNpadJoyAssignmentModeSingleByDefault,
"SetNpadJoyAssignmentModeSingleByDefault"},
{123, nullptr, "SetNpadJoyAssignmentModeSingleByDefault"},
{124, &Hid::SetNpadJoyAssignmentModeDual, "SetNpadJoyAssignmentModeDual"},
{125, nullptr, "MergeSingleJoyAsDualJoy"},
{126, nullptr, "StartLrAssignmentMode"},
{127, nullptr, "StopLrAssignmentMode"},
{128, &Hid::SetNpadHandheldActivationMode, "SetNpadHandheldActivationMode"},
{129, nullptr, "GetNpadHandheldActivationMode"},
{130, nullptr, "SwapNpadAssignment"},
{131, nullptr, "IsUnintendedHomeButtonInputProtectionEnabled"},
{132, nullptr, "EnableUnintendedHomeButtonInputProtection"},
{200, &Hid::GetVibrationDeviceInfo, "GetVibrationDeviceInfo"},
{201, &Hid::SendVibrationValue, "SendVibrationValue"},
{202, &Hid::GetActualVibrationValue, "GetActualVibrationValue"},
{203, &Hid::CreateActiveVibrationDeviceList, "CreateActiveVibrationDeviceList"},
{204, nullptr, "PermitVibration"},
{205, nullptr, "IsVibrationPermitted"},
{206, &Hid::SendVibrationValues, "SendVibrationValues"},
{300, nullptr, "ActivateConsoleSixAxisSensor"},
{301, nullptr, "StartConsoleSixAxisSensor"},
{302, nullptr, "StopConsoleSixAxisSensor"},
{400, nullptr, "IsUsbFullKeyControllerEnabled"},
{401, nullptr, "EnableUsbFullKeyController"},
{402, nullptr, "IsUsbFullKeyControllerConnected"},
{1000, nullptr, "SetNpadCommunicationMode"},
{1001, nullptr, "GetNpadCommunicationMode"},
};
RegisterHandlers(functions);
@@ -237,138 +286,144 @@ private:
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(RESULT_SUCCESS);
rb.PushIpcInterface<IAppletResource>(applet_resource);
LOG_DEBUG(Service_HID, "called");
NGLOG_DEBUG(Service_HID, "called");
}
void ActivateDebugPad(Kernel::HLERequestContext& ctx) {
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS);
LOG_WARNING(Service_HID, "(STUBBED) called");
NGLOG_WARNING(Service_HID, "(STUBBED) called");
}
void ActivateTouchScreen(Kernel::HLERequestContext& ctx) {
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS);
LOG_WARNING(Service_HID, "(STUBBED) called");
NGLOG_WARNING(Service_HID, "(STUBBED) called");
}
void ActivateMouse(Kernel::HLERequestContext& ctx) {
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS);
LOG_WARNING(Service_HID, "(STUBBED) called");
NGLOG_WARNING(Service_HID, "(STUBBED) called");
}
void ActivateKeyboard(Kernel::HLERequestContext& ctx) {
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS);
LOG_WARNING(Service_HID, "(STUBBED) called");
NGLOG_WARNING(Service_HID, "(STUBBED) called");
}
void StartSixAxisSensor(Kernel::HLERequestContext& ctx) {
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS);
LOG_WARNING(Service_HID, "(STUBBED) called");
NGLOG_WARNING(Service_HID, "(STUBBED) called");
}
void SetGyroscopeZeroDriftMode(Kernel::HLERequestContext& ctx) {
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS);
LOG_WARNING(Service_HID, "(STUBBED) called");
NGLOG_WARNING(Service_HID, "(STUBBED) called");
}
void SetSupportedNpadStyleSet(Kernel::HLERequestContext& ctx) {
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS);
LOG_WARNING(Service_HID, "(STUBBED) called");
NGLOG_WARNING(Service_HID, "(STUBBED) called");
}
void GetSupportedNpadStyleSet(Kernel::HLERequestContext& ctx) {
IPC::ResponseBuilder rb{ctx, 3};
rb.Push(RESULT_SUCCESS);
rb.Push<u32>(0);
LOG_WARNING(Service_HID, "(STUBBED) called");
NGLOG_WARNING(Service_HID, "(STUBBED) called");
}
void SetSupportedNpadIdType(Kernel::HLERequestContext& ctx) {
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS);
LOG_WARNING(Service_HID, "(STUBBED) called");
NGLOG_WARNING(Service_HID, "(STUBBED) called");
}
void ActivateNpad(Kernel::HLERequestContext& ctx) {
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS);
LOG_WARNING(Service_HID, "(STUBBED) called");
NGLOG_WARNING(Service_HID, "(STUBBED) called");
}
void AcquireNpadStyleSetUpdateEventHandle(Kernel::HLERequestContext& ctx) {
IPC::ResponseBuilder rb{ctx, 2, 1};
rb.Push(RESULT_SUCCESS);
rb.PushCopyObjects(event);
LOG_WARNING(Service_HID, "(STUBBED) called");
NGLOG_WARNING(Service_HID, "(STUBBED) called");
}
void GetPlayerLedPattern(Kernel::HLERequestContext& ctx) {
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS);
NGLOG_WARNING(Service_HID, "(STUBBED) called");
}
void SetNpadJoyHoldType(Kernel::HLERequestContext& ctx) {
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS);
LOG_WARNING(Service_HID, "(STUBBED) called");
NGLOG_WARNING(Service_HID, "(STUBBED) called");
}
void GetNpadJoyHoldType(Kernel::HLERequestContext& ctx) {
IPC::ResponseBuilder rb{ctx, 3};
rb.Push(RESULT_SUCCESS);
rb.Push(joy_hold_type);
LOG_WARNING(Service_HID, "(STUBBED) called");
NGLOG_WARNING(Service_HID, "(STUBBED) called");
}
void SetNpadJoyAssignmentModeSingleByDefault(Kernel::HLERequestContext& ctx) {
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS);
LOG_WARNING(Service_HID, "(STUBBED) called");
NGLOG_WARNING(Service_HID, "(STUBBED) called");
}
void SendVibrationValue(Kernel::HLERequestContext& ctx) {
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS);
LOG_WARNING(Service_HID, "(STUBBED) called");
NGLOG_WARNING(Service_HID, "(STUBBED) called");
}
void GetActualVibrationValue(Kernel::HLERequestContext& ctx) {
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS);
LOG_WARNING(Service_HID, "(STUBBED) called");
NGLOG_WARNING(Service_HID, "(STUBBED) called");
}
void SetNpadJoyAssignmentModeDual(Kernel::HLERequestContext& ctx) {
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS);
LOG_WARNING(Service_HID, "(STUBBED) called");
NGLOG_WARNING(Service_HID, "(STUBBED) called");
}
void SetNpadHandheldActivationMode(Kernel::HLERequestContext& ctx) {
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS);
LOG_WARNING(Service_HID, "(STUBBED) called");
NGLOG_WARNING(Service_HID, "(STUBBED) called");
}
void GetVibrationDeviceInfo(Kernel::HLERequestContext& ctx) {
IPC::ResponseBuilder rb{ctx, 4};
rb.Push(RESULT_SUCCESS);
rb.Push<u64>(0);
LOG_WARNING(Service_HID, "(STUBBED) called");
NGLOG_WARNING(Service_HID, "(STUBBED) called");
}
void CreateActiveVibrationDeviceList(Kernel::HLERequestContext& ctx) {
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(RESULT_SUCCESS);
rb.PushIpcInterface<IActiveVibrationDeviceList>();
LOG_DEBUG(Service_HID, "called");
NGLOG_DEBUG(Service_HID, "called");
}
void SendVibrationValues(Kernel::HLERequestContext& ctx) {
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS);
LOG_WARNING(Service_HID, "(STUBBED) called");
NGLOG_WARNING(Service_HID, "(STUBBED) called");
}
};
@@ -378,5 +433,4 @@ void InstallInterfaces(SM::ServiceManager& service_manager) {
std::make_shared<Hid>()->InstallAsService(service_manager);
}
} // namespace HID
} // namespace Service
} // namespace Service::HID

View File

@@ -7,8 +7,7 @@
#include "core/hle/service/service.h"
#include "core/settings.h"
namespace Service {
namespace HID {
namespace Service::HID {
// Begin enums and output structs
@@ -337,5 +336,4 @@ void ReloadInputDevices();
/// Registers all HID services with the specified service manager.
void InstallInterfaces(SM::ServiceManager& service_manager);
} // namespace HID
} // namespace Service
} // namespace Service::HID

View File

@@ -9,8 +9,7 @@
#include "core/hle/kernel/client_session.h"
#include "core/hle/service/lm/lm.h"
namespace Service {
namespace LM {
namespace Service::LM {
class Logger final : public ServiceFramework<Logger> {
public:
@@ -142,19 +141,19 @@ private:
if (header.IsTailLog()) {
switch (header.severity) {
case MessageHeader::Severity::Trace:
LOG_TRACE(Debug_Emulated, "%s", log_stream.str().c_str());
NGLOG_TRACE(Debug_Emulated, "{}", log_stream.str());
break;
case MessageHeader::Severity::Info:
LOG_INFO(Debug_Emulated, "%s", log_stream.str().c_str());
NGLOG_INFO(Debug_Emulated, "{}", log_stream.str());
break;
case MessageHeader::Severity::Warning:
LOG_WARNING(Debug_Emulated, "%s", log_stream.str().c_str());
NGLOG_WARNING(Debug_Emulated, "{}", log_stream.str());
break;
case MessageHeader::Severity::Error:
LOG_ERROR(Debug_Emulated, "%s", log_stream.str().c_str());
NGLOG_ERROR(Debug_Emulated, "{}", log_stream.str());
break;
case MessageHeader::Severity::Critical:
LOG_CRITICAL(Debug_Emulated, "%s", log_stream.str().c_str());
NGLOG_CRITICAL(Debug_Emulated, "{}", log_stream.str());
break;
}
}
@@ -179,7 +178,7 @@ void LM::Initialize(Kernel::HLERequestContext& ctx) {
rb.Push(RESULT_SUCCESS);
rb.PushIpcInterface<Logger>();
LOG_DEBUG(Service_LM, "called");
NGLOG_DEBUG(Service_LM, "called");
}
LM::LM() : ServiceFramework("lm") {
@@ -189,5 +188,4 @@ LM::LM() : ServiceFramework("lm") {
RegisterHandlers(functions);
}
} // namespace LM
} // namespace Service
} // namespace Service::LM

View File

@@ -8,8 +8,7 @@
#include "core/hle/kernel/kernel.h"
#include "core/hle/service/service.h"
namespace Service {
namespace LM {
namespace Service::LM {
class LM final : public ServiceFramework<LM> {
public:
@@ -23,5 +22,4 @@ private:
/// Registers all LM services with the specified service manager.
void InstallInterfaces(SM::ServiceManager& service_manager);
} // namespace LM
} // namespace Service
} // namespace Service::LM

View File

@@ -7,14 +7,13 @@
#include "core/hle/service/nfp/nfp.h"
#include "core/hle/service/nfp/nfp_user.h"
namespace Service {
namespace NFP {
namespace Service::NFP {
Module::Interface::Interface(std::shared_ptr<Module> module, const char* name)
: ServiceFramework(name), module(std::move(module)) {}
void Module::Interface::Unknown(Kernel::HLERequestContext& ctx) {
LOG_WARNING(Service_NFP, "(STUBBED) called");
NGLOG_WARNING(Service_NFP, "(STUBBED) called");
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS);
}
@@ -24,5 +23,4 @@ void InstallInterfaces(SM::ServiceManager& service_manager) {
std::make_shared<NFP_User>(module)->InstallAsService(service_manager);
}
} // namespace NFP
} // namespace Service
} // namespace Service::NFP

View File

@@ -6,8 +6,7 @@
#include "core/hle/service/service.h"
namespace Service {
namespace NFP {
namespace Service::NFP {
class Module final {
public:
@@ -24,5 +23,4 @@ public:
void InstallInterfaces(SM::ServiceManager& service_manager);
} // namespace NFP
} // namespace Service
} // namespace Service::NFP

View File

@@ -4,8 +4,7 @@
#include "core/hle/service/nfp/nfp_user.h"
namespace Service {
namespace NFP {
namespace Service::NFP {
NFP_User::NFP_User(std::shared_ptr<Module> module)
: Module::Interface(std::move(module), "nfp:user") {
@@ -15,5 +14,4 @@ NFP_User::NFP_User(std::shared_ptr<Module> module)
RegisterHandlers(functions);
}
} // namespace NFP
} // namespace Service
} // namespace Service::NFP

View File

@@ -6,13 +6,11 @@
#include "core/hle/service/nfp/nfp.h"
namespace Service {
namespace NFP {
namespace Service::NFP {
class NFP_User final : public Module::Interface {
public:
explicit NFP_User(std::shared_ptr<Module> module);
};
} // namespace NFP
} // namespace Service
} // namespace Service::NFP

View File

@@ -9,8 +9,7 @@
#include "core/hle/service/nifm/nifm_s.h"
#include "core/hle/service/nifm/nifm_u.h"
namespace Service {
namespace NIFM {
namespace Service::NIFM {
class IScanRequest final : public ServiceFramework<IScanRequest> {
public:
@@ -63,24 +62,24 @@ public:
private:
void GetRequestState(Kernel::HLERequestContext& ctx) {
LOG_WARNING(Service_NIFM, "(STUBBED) called");
NGLOG_WARNING(Service_NIFM, "(STUBBED) called");
IPC::ResponseBuilder rb{ctx, 3};
rb.Push(RESULT_SUCCESS);
rb.Push<u32>(0);
}
void GetResult(Kernel::HLERequestContext& ctx) {
LOG_WARNING(Service_NIFM, "(STUBBED) called");
NGLOG_WARNING(Service_NIFM, "(STUBBED) called");
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS);
}
void GetSystemEventReadableHandles(Kernel::HLERequestContext& ctx) {
LOG_WARNING(Service_NIFM, "(STUBBED) called");
NGLOG_WARNING(Service_NIFM, "(STUBBED) called");
IPC::ResponseBuilder rb{ctx, 2, 2};
rb.Push(RESULT_SUCCESS);
rb.PushCopyObjects(event1, event2);
}
void Cancel(Kernel::HLERequestContext& ctx) {
LOG_WARNING(Service_NIFM, "(STUBBED) called");
NGLOG_WARNING(Service_NIFM, "(STUBBED) called");
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS);
}
@@ -106,7 +105,7 @@ public:
private:
void GetClientId(Kernel::HLERequestContext& ctx) {
LOG_WARNING(Service_NIFM, "(STUBBED) called");
NGLOG_WARNING(Service_NIFM, "(STUBBED) called");
IPC::ResponseBuilder rb{ctx, 4};
rb.Push(RESULT_SUCCESS);
rb.Push<u64>(0);
@@ -117,7 +116,7 @@ private:
rb.Push(RESULT_SUCCESS);
rb.PushIpcInterface<IScanRequest>();
LOG_DEBUG(Service_NIFM, "called");
NGLOG_DEBUG(Service_NIFM, "called");
}
void CreateRequest(Kernel::HLERequestContext& ctx) {
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
@@ -125,10 +124,10 @@ private:
rb.Push(RESULT_SUCCESS);
rb.PushIpcInterface<IRequest>();
LOG_DEBUG(Service_NIFM, "called");
NGLOG_DEBUG(Service_NIFM, "called");
}
void RemoveNetworkProfile(Kernel::HLERequestContext& ctx) {
LOG_WARNING(Service_NIFM, "(STUBBED) called");
NGLOG_WARNING(Service_NIFM, "(STUBBED) called");
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS);
}
@@ -138,7 +137,7 @@ private:
rb.Push(RESULT_SUCCESS);
rb.PushIpcInterface<INetworkProfile>();
LOG_DEBUG(Service_NIFM, "called");
NGLOG_DEBUG(Service_NIFM, "called");
}
};
@@ -188,14 +187,14 @@ void Module::Interface::CreateGeneralServiceOld(Kernel::HLERequestContext& ctx)
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(RESULT_SUCCESS);
rb.PushIpcInterface<IGeneralService>();
LOG_DEBUG(Service_NIFM, "called");
NGLOG_DEBUG(Service_NIFM, "called");
}
void Module::Interface::CreateGeneralService(Kernel::HLERequestContext& ctx) {
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(RESULT_SUCCESS);
rb.PushIpcInterface<IGeneralService>();
LOG_DEBUG(Service_NIFM, "called");
NGLOG_DEBUG(Service_NIFM, "called");
}
Module::Interface::Interface(std::shared_ptr<Module> module, const char* name)
@@ -208,5 +207,4 @@ void InstallInterfaces(SM::ServiceManager& service_manager) {
std::make_shared<NIFM_U>(module)->InstallAsService(service_manager);
}
} // namespace NIFM
} // namespace Service
} // namespace Service::NIFM

View File

@@ -6,8 +6,7 @@
#include "core/hle/service/service.h"
namespace Service {
namespace NIFM {
namespace Service::NIFM {
class Module final {
public:
@@ -25,5 +24,4 @@ public:
void InstallInterfaces(SM::ServiceManager& service_manager);
} // namespace NIFM
} // namespace Service
} // namespace Service::NIFM

View File

@@ -4,8 +4,7 @@
#include "core/hle/service/nifm/nifm_a.h"
namespace Service {
namespace NIFM {
namespace Service::NIFM {
NIFM_A::NIFM_A(std::shared_ptr<Module> module) : Module::Interface(std::move(module), "nifm:a") {
static const FunctionInfo functions[] = {
@@ -15,5 +14,4 @@ NIFM_A::NIFM_A(std::shared_ptr<Module> module) : Module::Interface(std::move(mod
RegisterHandlers(functions);
}
} // namespace NIFM
} // namespace Service
} // namespace Service::NIFM

View File

@@ -6,13 +6,11 @@
#include "core/hle/service/nifm/nifm.h"
namespace Service {
namespace NIFM {
namespace Service::NIFM {
class NIFM_A final : public Module::Interface {
public:
explicit NIFM_A(std::shared_ptr<Module> module);
};
} // namespace NIFM
} // namespace Service
} // namespace Service::NIFM

View File

@@ -4,8 +4,7 @@
#include "core/hle/service/nifm/nifm_s.h"
namespace Service {
namespace NIFM {
namespace Service::NIFM {
NIFM_S::NIFM_S(std::shared_ptr<Module> module) : Module::Interface(std::move(module), "nifm:s") {
static const FunctionInfo functions[] = {
@@ -15,5 +14,4 @@ NIFM_S::NIFM_S(std::shared_ptr<Module> module) : Module::Interface(std::move(mod
RegisterHandlers(functions);
}
} // namespace NIFM
} // namespace Service
} // namespace Service::NIFM

View File

@@ -6,13 +6,11 @@
#include "core/hle/service/nifm/nifm.h"
namespace Service {
namespace NIFM {
namespace Service::NIFM {
class NIFM_S final : public Module::Interface {
public:
explicit NIFM_S(std::shared_ptr<Module> module);
};
} // namespace NIFM
} // namespace Service
} // namespace Service::NIFM

View File

@@ -4,8 +4,7 @@
#include "core/hle/service/nifm/nifm_u.h"
namespace Service {
namespace NIFM {
namespace Service::NIFM {
NIFM_U::NIFM_U(std::shared_ptr<Module> module) : Module::Interface(std::move(module), "nifm:u") {
static const FunctionInfo functions[] = {
@@ -15,5 +14,4 @@ NIFM_U::NIFM_U(std::shared_ptr<Module> module) : Module::Interface(std::move(mod
RegisterHandlers(functions);
}
} // namespace NIFM
} // namespace Service
} // namespace Service::NIFM

View File

@@ -6,13 +6,11 @@
#include "core/hle/service/nifm/nifm.h"
namespace Service {
namespace NIFM {
namespace Service::NIFM {
class NIFM_U final : public Module::Interface {
public:
explicit NIFM_U(std::shared_ptr<Module> module);
};
} // namespace NIFM
} // namespace Service
} // namespace Service::NIFM

View File

@@ -5,12 +5,10 @@
#include "core/hle/service/ns/ns.h"
#include "core/hle/service/ns/pl_u.h"
namespace Service {
namespace NS {
namespace Service::NS {
void InstallInterfaces(SM::ServiceManager& service_manager) {
std::make_shared<PL_U>()->InstallAsService(service_manager);
}
} // namespace NS
} // namespace Service
} // namespace Service::NS

View File

@@ -6,11 +6,9 @@
#include "core/hle/service/service.h"
namespace Service {
namespace NS {
namespace Service::NS {
/// Registers all NS services with the specified service manager.
void InstallInterfaces(SM::ServiceManager& service_manager);
} // namespace NS
} // namespace Service
} // namespace Service::NS

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