Compare commits

...

143 Commits

Author SHA1 Message Date
Lioncash
5eb057f422 kernel/object: Amend handle types to distinguish between readable and writable events
Two kernel object should absolutely never have the same handle ID type.
This can cause incorrect behavior when it comes to retrieving object
types from the handle table. In this case it allows converting a
WritableEvent into a ReadableEvent and vice-versa, which is undefined
behavior, since the object types are not the same.

This also corrects ClearEvent() to check both kernel types like the
kernel itself does.
2018-12-04 02:20:47 -05:00
Mat M
adc4d332fc Merge pull request #1852 from VPeruS/fix-format-string
[Kernel::CreateThread] Match format specifiers to LOG_TRACE's arguments
2018-12-03 22:25:29 -05:00
V.Kalyuzhny
b330b495dc [Kernel::CreateThread] Match format specifiers to LOG_TRACE's arguments 2018-12-04 05:13:50 +02:00
bunnei
9f1ac96afa Merge pull request #1840 from lioncash/info
svc: Reorganize svcGetInfo, handle more error cases for existing implemented info categories
2018-12-03 18:46:22 -05:00
bunnei
76525013c0 Merge pull request #1842 from lioncash/slot
yuzu/configuration: Minor clean-up related changes
2018-12-03 17:12:01 -05:00
bunnei
f6b22d9251 Merge pull request #1835 from lioncash/cache-global
filesystem: De-globalize registered_cache_union
2018-12-03 17:11:26 -05:00
bunnei
8a12daac8c Merge pull request #1822 from ReinUsesLisp/glsl-scope
gl_shader_decompiler: Introduce a scoped object and style changes
2018-12-03 17:10:02 -05:00
bunnei
ef69b4b830 Merge pull request #1803 from DarkLordZach/k-able-event
kernel: Divide Event into ReadableEvent and WritableEvent
2018-12-03 17:05:57 -05:00
bunnei
f7d5f72944 Merge pull request #1833 from lioncash/clean
service/fsp_srv: Implement CleanDirectoryRecursively
2018-12-03 17:04:05 -05:00
bunnei
118f402382 Merge pull request #1839 from lioncash/init
service/audio/audout_u: Amend constructor initialization list order
2018-12-03 17:03:00 -05:00
bunnei
a238cdb5ca Merge pull request #1841 from ogniK5377/npad-mode-fix
Fixed crash with SetNpadMode
2018-12-03 17:02:40 -05:00
Sebastian Valle
1ad158b2bb Merge pull request #1843 from lioncash/table
hle/service: Update function tables for erpt:c and usb's IClientEpSession
2018-12-03 12:21:28 -05:00
Lioncash
6306e54f45 service/usb: Update function table
Updates the function table for IClientEpSession based off information
provided by SwitchBrew.
2018-12-02 15:49:40 -05:00
Lioncash
f933b3370e service/erpt: Update function table
Updates the function table according to information provided by
SwitchBrew.
2018-12-02 15:46:44 -05:00
Lioncash
195cad9635 yuzu/configuration: Make slots private where applicable
These slots are only ever attached to event handling mechanisms within
the class itself, they're never used externally. Because of this, we can
make the functions private.

This also removes redundant usages of the private access specifier.
2018-12-02 14:18:36 -05:00
Lioncash
eabfb7730d yuzu/configuration: Add missing override specifiers to configuration-related classes
Resolves trivial compiler warnings.
2018-12-02 14:18:36 -05:00
Lioncash
f3253d0f14 yuzu/configuration/configure_input: Default destructor in the cpp file
The previous code could potentially be a compilation issue waiting to
occur, given we forward declare the type for a std::unique_ptr. If the
complete definition of the forward declared type isn't visible in a
translation unit that the class is used in, then it would fail to
compile.

Defaulting the destructor in a cpp file ensures the std::unique_ptr's
destructor is only invoked where its complete type is known.
2018-12-02 14:18:26 -05:00
David Marcec
a9223c8182 Fixed crash with SetNpadMode
fixed crash due to handheld
2018-12-03 02:45:08 +11:00
Lioncash
7fe27de26e svc: Use the current process' handle table for retrieving the process instance to act upon
The kernel uses the handle table of the current process to retrieve the
process that should be used to retrieve certain information. To someone
not familiar with the kernel, this might raise the question of "Ok,
sounds nice, but doesn't this make it impossible to retrieve information
about the current process?".

No, it doesn't, because HandleTable instances in the kernel have the
notion of a "pseudo-handle", where certain values allow the kernel to
lookup objects outside of a given handle table. Currently, there's only
a pseudo-handle for the current process (0xFFFF8001) and a pseudo-handle
for the current thread (0xFFFF8000), so to retrieve the current process,
one would just pass 0xFFFF8001 into svcGetInfo.

The lookup itself in the handle table would be something like:

template <typename T>
T* Lookup(Handle handle) {
    if (handle == PSEUDO_HANDLE_CURRENT_PROCESS) {
        return CurrentProcess();
    }

    if (handle == PSUEDO_HANDLE_CURRENT_THREAD) {
        return CurrentThread();
    }

    return static_cast<T*>(&objects[handle]);
}

which, as is shown, allows accessing the current process or current
thread, even if those two objects aren't actually within the HandleTable
instance.
2018-12-02 03:41:49 -05:00
Lioncash
6712e7402c svc: Reorganize svcGetInfo, handle more error cases for existing implemented info categories
Our implementation of svcGetInfo was slightly incorrect in that we
weren't doing proper error checking everywhere. Instead, reorganize it
to be similar to how the kernel seems to do it.
2018-12-02 03:40:10 -05:00
Lioncash
57ac068a23 service/audio/audout_u: Amend constructor initialization list order
Orders the constructor initializer list the same way the members of the
class are declared. Prevents -Wreorder warnings
2018-12-01 23:56:20 -05:00
bunnei
7ce17b2cf6 Merge pull request #1827 from ReinUsesLisp/clip-and-shader
gl_rasterizer: Enable clip distances when set in register and in shader
2018-12-01 23:51:47 -05:00
bunnei
80aa124b1d Merge pull request #1825 from ReinUsesLisp/shader-pipeline-cache
gl_shader_manager: Update pipeline when programs have changed
2018-12-01 23:48:55 -05:00
bunnei
a6805e58ce Merge pull request #1795 from ReinUsesLisp/vc-cleanup
video_core: Minor style changes
2018-12-01 23:46:18 -05:00
bunnei
0e9be7be37 Merge pull request #1823 from bunnei/fix-surface-copy
gl_rasterizer_cache: Fix several surface copy issues.
2018-12-01 23:44:32 -05:00
Lioncash
db4523f1ec filesystem: De-globalize registered_cache_union
We can just return a new instance of this when it's requested. This only
ever holds pointers to the existing registed caches, so it's not a large
object. Plus, this also gets rid of the need to keep around a separate
member function just to properly clear out the union.

Gets rid of one of five globals in the filesystem code.
2018-12-01 23:43:23 -05:00
bunnei
c5e781e72a Merge pull request #1832 from Simek/remove-game-list-border
UI: Remove border from Game List
2018-12-01 22:26:34 -05:00
bunnei
97e73591e3 Merge pull request #1830 from Subv/vi_ub
Services/VI: Dereferencing an uninitialized std::optional is undefined behavior.
2018-12-01 22:25:10 -05:00
Lioncash
e88cdcc912 Fix debug build
A non-existent parameter was left in some formatting calls (the logging
macro for which only does anything meaningful on debug builds)
2018-12-01 02:11:42 -05:00
Lioncash
0ccaaafca3 file_sys: Override missing mutating functions to be stubbed out for ReadOnlyVfsDirectory by default
Ensures that read only indeed means read only.
2018-11-30 23:52:56 -05:00
Lioncash
a7d9fe993a service/fsp_srv: Implement CleanDirectoryRecursively
This is the same behavior-wise as DeleteDirectoryRecursively, with the
only difference being that it doesn't delete the top level directory in
the hierarchy, so given:

root_dir/
  - some_dir/
    - File.txt
  - OtherFile.txt

The end result is just:

root_dir/
2018-11-30 20:17:28 -05:00
Bartosz Kaszubowski
5f07ca3dce remove border from GameList 2018-11-30 23:35:08 +01:00
Subv
583bd20f02 Services/VI: Dereferencing an uninitialized std::optional is undefined behavior.
Assert that it is not empty before using it in the DequeueBuffer wait callback.
2018-11-30 16:06:49 -05:00
bunnei
b7104263ba Merge pull request #1829 from lioncash/lang
service/set: Implement MakeLanguageCode
2018-11-30 10:53:13 -05:00
Lioncash
308bbba8b9 service/set: Convert GetLanguageCode over to using PushEnum()
This code was around prior to the introduction of PushEnum, so convert
it over so we don't need to cast here.
2018-11-30 09:08:07 -05:00
Lioncash
7c04fe22b4 service/set: Implement MakeLanguageCode
This function simply converts a given index into a language code.
2018-11-30 09:08:03 -05:00
Lioncash
4b950728fd configure_input: Amend clang-format discrepancies 2018-11-30 03:31:56 -05:00
bunnei
0f43564d09 gl_rasterizer_cache: Update AccurateCopySurface to flush complete source surface.
- Fixes issues with Breath of the Wild with use_accurate_gpu_emulation setting.
2018-11-29 20:10:11 -05:00
ReinUsesLisp
2908d30274 gl_rasterizer: Enable clip distances when set in register and in shader 2018-11-29 16:58:20 -03:00
ReinUsesLisp
e8620eaa9a gl_shader_manager: Update pipeline when programs have changed 2018-11-29 16:26:42 -03:00
Zach Hilman
170d707850 hle_ipc: Refactor SleepClientThread to avoid ReadableEvent 2018-11-29 09:14:20 -05:00
Zach Hilman
a342bcc9b1 kernel/event: Reference ReadableEvent from WritableEvent 2018-11-29 08:48:40 -05:00
Zach Hilman
ff610103b5 core: Port all current usages of Event to Readable/WritableEvent 2018-11-29 08:45:41 -05:00
Zach Hilman
a56fc84e7a hle_ipc: Use event pair for SleepClientThread 2018-11-29 08:42:26 -05:00
Zach Hilman
c61d2a2841 kernel: Add named event table
Used to store ReadableEvents of all events on the system.
2018-11-29 08:42:26 -05:00
Zach Hilman
c713383816 kernel: Divide Event into ReadableEvent and WritableEvent
More hardware accurate. On the actual system, there is a differentiation between the signaler and signalee, they form a client/server relationship much like ServerPort and ClientPort.
2018-11-29 08:42:26 -05:00
Zach Hilman
d92989e787 kernel/object: Add descriptions to ResetTypes 2018-11-29 08:42:26 -05:00
bunnei
7befe0134d Merge pull request #1768 from greggameplayer/patch-2
Uncheck automatically joycons docked when docked mode is enable
2018-11-29 01:00:09 -05:00
bunnei
1e49a85106 Merge pull request #1801 from ogniK5377/log-before-execute
Changed logging to be "Log before execution", Added more error logging, all services/svc should now log on some level
2018-11-29 00:58:46 -05:00
bunnei
3d3cc35ee7 gl_rasterizer_cache: Remove BlitSurface and replace with more accurate copy.
- BlitSurface with different texture targets is inherently broken.
- When target is the same, we can just use FastCopySurface.
- Fixes rendering issues with Breath of the Wild.
2018-11-28 21:56:21 -05:00
ReinUsesLisp
eb700afcf0 gl_shader_decompiler: Remove texture temporal in TLD4 2018-11-28 23:46:16 -03:00
ReinUsesLisp
8d58e5da71 gl_shader_decompiler: Flip negated if else statement 2018-11-28 23:46:16 -03:00
ReinUsesLisp
f4abebd731 gl_shader_decompiler: Use GLSL scope on instructions unrelated to textures 2018-11-28 23:46:14 -03:00
ReinUsesLisp
78fc8f6b66 gl_shader_decompiler: Move texture code generation into lambdas 2018-11-28 23:45:53 -03:00
ReinUsesLisp
ab13b628d0 gl_shader_decompiler: Clean up texture instructions 2018-11-28 23:45:53 -03:00
ReinUsesLisp
6a642022dd gl_shader_decompiler: Scope GLSL variables with a scoped object 2018-11-28 23:45:51 -03:00
ReinUsesLisp
037449668e gl_rasterizer: Signal UNIMPLEMENTED when rt_separate_frag_data is not zero 2018-11-28 21:26:22 -03:00
ReinUsesLisp
653d7a3f0d gl_rasterizer_cache: Use brackets for two-line single-expresion blocks 2018-11-28 21:18:14 -03:00
ReinUsesLisp
432a9872ed gl_rasterizer: Remove unused struct declarations 2018-11-28 21:18:13 -03:00
ReinUsesLisp
22c7c710b4 gl_rasterizer: Remove extension booleans 2018-11-28 21:18:13 -03:00
bunnei
5a9a84994a Merge pull request #1808 from Tinob/master
Fix clip distance and viewport
2018-11-28 17:47:28 -05:00
bunnei
3fe8ab0d99 Merge pull request #1786 from Tinob/DepthClamp
Add Depth Clamp Support
2018-11-28 17:46:55 -05:00
bunnei
c5ab648554 Merge pull request #1817 from DarkLordZach/npad-idx-fix
npad: Use NPadIdToIndex to prevent invalid array access
2018-11-28 17:46:17 -05:00
bunnei
6f849887c9 Merge pull request #1792 from bunnei/dma-pusher
gpu: Rewrite GPU command list processing with DmaPusher class.
2018-11-28 10:12:37 -05:00
Zach Hilman
299224790c npad: Use NPadIdToIndex to prevent invalid array access 2018-11-28 09:01:58 -05:00
bunnei
881f5ad70f Merge pull request #1735 from FernandoS27/tex-spacing
Texture decoder: Implemented Tile Width Spacing
2018-11-27 19:21:17 -05:00
bunnei
adb882bf90 Merge pull request #1814 from lioncash/ptr
file_sys/registered_cache: Use regular const references instead of std::shared_ptr for InstallEntry()
2018-11-27 19:20:12 -05:00
bunnei
ac74b71d75 dma_pushbuffer: Optimize to avoid loop and copy on Push. 2018-11-27 19:17:33 -05:00
bunnei
c568f5cea7 gpu: Move command list profiling to DmaPusher::DispatchCalls. 2018-11-27 18:42:21 -05:00
bunnei
e89a3b9e59 Merge pull request #1811 from lioncash/input
yuzu/input: Minor changes
2018-11-27 18:38:12 -05:00
bunnei
71dfe4a7ae Merge pull request #1815 from DarkLordZach/npad-pos-fix
npad: Fix copy/paste error with LED position assignments
2018-11-27 17:26:58 -05:00
Zach Hilman
6df74ff579 npad: Fix copy/paste error with LED position assignments 2018-11-27 17:23:44 -05:00
Lioncash
2a22c1b27e yuzu/configure_input_player: Use std::size_t to represent the player index instead of u8
Prevents compiler warnings related to truncation when invoking the
dialog. It's also extremely suspect to use a u8 value here instead of a
more general type to begin with.
2018-11-27 16:37:21 -05:00
Lioncash
0782d3971b yuzu/configure_input: Make CallConfigureDialog a non-member template function
This doesn't depend on any part of the private interface, so it can be
made a non-member internal function.
2018-11-27 16:37:18 -05:00
bunnei
3cc204aff8 Merge pull request #1802 from DarkLordZach/user-data-storage
profile_manager: Save and load ProfileData from disk
2018-11-27 16:36:23 -05:00
Lioncash
7b1aaaa069 file_sys/registered_cache: Remove unused <map> include 2018-11-27 16:33:18 -05:00
Lioncash
d72c809030 file_sys/registered_cache: Use regular const references instead of std::shared_ptr for InstallEntry()
These parameters don't need to utilize a shared lifecycle directly in
the interface. Instead, the caller should provide a regular reference
for the function to use. This also allows the type system to flag
attempts to pass nullptr and makes it more generic, since it can now be
used in contexts where a shared_ptr isn't being used (in other words, we
don't constrain the usage of the interface to a particular mode of
memory management).
2018-11-27 16:33:14 -05:00
bunnei
bf055e14ab Merge pull request #1812 from lioncash/nacp
control_metadata: Correct typo in language name (Portugese -> Portuguese)
2018-11-27 16:29:53 -05:00
bunnei
066140854a Merge pull request #1813 from ReinUsesLisp/fixup-clip
gl_shader_decompiler: Fixup clip distance index
2018-11-27 16:28:55 -05:00
ReinUsesLisp
2e9b90abad gl_shader_decompiler: Fixup clip distance index 2018-11-27 15:35:26 -03:00
Lioncash
d4e3d567ce control_metadata: Correct typo in language name (Portugese -> Portuguese)
While we're at it, organize the array linearly, since clang formats the
array elements quite wide length-wise with the addition of the missing
'u'.

Technically also fixes patch lookup and icon lookup with Portuguese,
though I doubt anyone has actually run into this issue.
2018-11-27 13:21:46 -05:00
bunnei
5bea164a77 Merge pull request #1810 from degasus/dirty_flags
gl_rasterizer: Fixup for #1723.
2018-11-27 10:46:49 -05:00
Lioncash
11cf13a6e1 yuzu/configure_input_player: Use a lambda expression instead of std::bind
std::bind is the pre-C++11 way of doing this.
2018-11-27 05:08:13 -05:00
Lioncash
73a48d6523 yuzu/configure_input_player: Amend constructor initializer list order
Orders the elements the way they would actually be initialized in.
Resolves compiler warnings with gcc and clang
2018-11-27 05:04:51 -05:00
Lioncash
53bff53791 yuzu/configure_input: Remove unused function MoveGridElement 2018-11-27 05:03:26 -05:00
Lioncash
d67e88e59c yuzu/configure_input*: Move data members after function declarations
The common pattern is to put the data members after the function
interface where applicable.
2018-11-27 05:02:15 -05:00
Lioncash
ec7ea4ae96 yuzu/configure_input: Remove unnecessary includes 2018-11-27 05:00:56 -05:00
Markus Wick
8747f5fc0d gl_rasterizer: Fixup for #1723.
On invalidating the streaming buffer, we need to reupload all vertex buffers.
But we don't need to reconfigure the vertex format.
This was a (silly) misstake in #1723.

Thanks at Rodrigo for discovering the issue.

Fun fact, as configuring the vertex format also invalidate the vertex buffer,
this misstake had no affect on the behavior.
2018-11-27 10:32:41 +01:00
bunnei
1cd40f107f Merge pull request #1806 from ReinUsesLisp/morton-fixup
morton: Fixup compiler warning
2018-11-26 23:22:59 -05:00
bunnei
11c17465d8 Merge pull request #1804 from lioncash/cast
gdbstub: Silence value truncation warning within FpuWrite()
2018-11-26 23:19:40 -05:00
bunnei
abea6fa90c gpu: Rewrite GPU command list processing with DmaPusher class.
- More accurate impl., fixes Undertale (among other games).
2018-11-26 23:14:01 -05:00
bunnei
852a462df3 Merge pull request #1805 from lioncash/resource
svc: Implement svcCreateResourceLimit, svcGetResourceLimitCurrentValue(), svcGetResourceLimitLimitValue(), and svcSetResourceLimitLimitValue()
2018-11-26 22:59:51 -05:00
Rodolfo Bogado
6710eb4892 remove viewport_transform_enabled as it seems to be inactive when valid transforms are used. 2018-11-27 00:04:33 -03:00
Lioncash
5905162e36 svc: Implement svcSetResourceLimitLimitValue()
The opposite of the getter functions, this function sets the limit value
for a particular ResourceLimit resource category, with the restriction
that the  new limit value must be equal to or greater than the current
resource value. If this is violated, then ERR_INVALID_STATE is returned.

e.g.

Assume:

current[Events] = 10;
limit[Events] = 20;

a call to this service function lowering the limit value to 10 would be
fine, however, attempting to lower it to 9 in this case would cause an
invalid state error.
2018-11-26 21:23:15 -05:00
Lioncash
eb5596044d svc: Implement svcGetResourceLimitCurrentValue()
This kernel service function is essentially the exact same as
svcGetResourceLimitLimitValue(), with the only difference being that it
retrieves the current value for a given resource category using the
provided resource limit handle, rather than retrieving the limiting
value of that resource limit instance.

Given these are exactly the same and only differ on returned values, we
can extract the existing code for svcGetResourceLimitLimitValue() to
handle both values.
2018-11-26 21:23:11 -05:00
ReinUsesLisp
237c2026e9 morton: Fixup compiler warning 2018-11-26 23:22:57 -03:00
Lioncash
1d6399c222 svc: Implement svcGetResourceLimitLimitValue()
This kernel service function retrieves the maximum allowable value for
a provided resource category for a given resource limit instance. Given
we already have the functionality added to the resource limit instance
itself, it's sufficient to just hook it up.

The error scenarios for this are:

1. If an invalid resource category type is provided, then ERR_INVALID_ENUM is returned.

2. If an invalid handle is provided, then ERR_INVALID_HANDLE is returned (bad thing goes in, bad thing goes out, as one would expect).

If neither of the above error cases occur, then the out parameter is
provided with the maximum limit value for the given category and success
is returned.
2018-11-26 21:12:13 -05:00
Lioncash
4ef2af8c98 svc: Implement svcCreateResourceLimit()
This function simply creates a ResourceLimit instance and attempts to
create a handle for it within the current process' handle table. If the
kernal fails to either create the ResourceLimit instance or create a
handle for the ResourceLimit instance, it returns a failure code
(OUT_OF_RESOURCE, and HANDLE_TABLE_FULL respectively). Finally, it exits
by providing the output parameter with the handle value for the
ResourceLimit instance and returning that it was successful.

Note: We do not return OUT_OF_RESOURCE because, if yuzu runs out of
available memory, then new will currently throw. We *could* allocate the
kernel instance with std::nothrow, however this would be inconsistent
with how all other kernel objects are currently allocated.
2018-11-26 21:10:31 -05:00
David Marcec
cc4521fc70 Added comment on Main memory size for more clarity 2018-11-27 12:56:50 +11:00
David Marcec
f058de337e Made svcSetHeapSize and svcCreateSharedMemory more readable 2018-11-27 12:53:18 +11:00
David Marcec
f271316822 Reworked svcs slightly, improved error messages in AM and fsp_srv 2018-11-27 12:29:06 +11:00
Lioncash
474c745502 gdbstub: Silence value truncation warning within FpuWrite()
Previously this would cause an implicit truncation warning about
assigning a u64 value to a u32 value without an explicit cast.
2018-11-26 19:58:23 -05:00
Rodolfo Bogado
dfdbfa69e5 Implement depth clamp 2018-11-26 20:56:32 -03:00
Rodolfo Bogado
8e971f5062 Add support for Clip Distance enabled register 2018-11-26 20:45:21 -03:00
bunnei
1856d0ee8a Merge pull request #1794 from Tinob/master
Add support for viewport_transfom_enable register
2018-11-26 18:34:09 -05:00
bunnei
67a154e23d Merge pull request #1723 from degasus/dirty_flags
gl_rasterizer: Skip VB upload if the state is clean.
2018-11-26 18:33:22 -05:00
Marcos
cb8d51e37e GPU States: Implement Polygon Offset. This is used in SMO all the time. (#1784)
* GPU States: Implement Polygon Offset. This is used in SMO all the time.

* Clang Format fixes.

* Initialize polygon_offset in the constructor.
2018-11-26 18:31:44 -05:00
bunnei
7684f4d0cf Merge pull request #1713 from FernandoS27/bra-cc
Implemented BRA CC conditional and FSET CC Setting
2018-11-26 18:28:03 -05:00
bunnei
a41943dc55 Merge pull request #1798 from ReinUsesLisp/y-direction
gl_shader_decompiler: Implement S2R's Y_DIRECTION
2018-11-26 18:25:42 -05:00
FernandoS27
ddfbe0b58d Implemented Tile Width Spacing 2018-11-26 09:05:12 -04:00
David Marcec
dace6087d6 Fixed hwopus compile error 2018-11-26 21:52:10 +11:00
David Marcec
3d627df4d8 Improved error messages in AM, HwOpus and NvMap 2018-11-26 20:05:09 +11:00
David Marcec
9662ca918d Improved error messages for SVCs 2018-11-26 19:47:39 +11:00
David Marcec
a2cc3b10bb Changed logging to be "Log before execution", Added more error logging, all services should now log on some level 2018-11-26 17:06:13 +11:00
bunnei
f9a211220c Merge pull request #1763 from ReinUsesLisp/bfi
gl_shader_decompiler: Implement BFI_IMM_R
2018-11-25 23:04:57 -05:00
bunnei
ee764c3b4b Merge pull request #1793 from lioncash/ref
service/sm: Take std::string by const reference in UnregisterService
2018-11-25 23:04:21 -05:00
bunnei
d7d1ab15b6 Merge pull request #1760 from ReinUsesLisp/r2p
gl_shader_decompiler: Implement R2P_IMM
2018-11-25 22:38:42 -05:00
bunnei
0394813401 Merge pull request #1782 from FernandoS27/dc
Fixed Coordinate Encodings in TEX and TEXS instructions
2018-11-25 22:36:25 -05:00
bunnei
8ce90a4f0b Merge pull request #1783 from ReinUsesLisp/clip-distances
gl_shader_decompiler: Implement clip distances
2018-11-25 22:35:30 -05:00
bunnei
ceb4bc22a4 Merge pull request #1796 from ReinUsesLisp/morton-move
video_core: Move morton functions out of gl_rasterizer_cache
2018-11-25 22:35:12 -05:00
Mat M
94fce28010 Merge pull request #1800 from encounter/svcgetinfo
svc: Return ERR_INVALID_ENUM_VALUE from svcGetInfo
2018-11-25 16:52:56 -05:00
Luke Street
94e8dfc0c7 svc: Return ERR_INVALID_ENUM_VALUE from svcGetInfo 2018-11-25 16:48:44 -05:00
Rodolfo Bogado
415e8383ba Limit the amount of viewports tested for state changes only to the usable ones 2018-11-25 12:18:29 -03:00
ReinUsesLisp
924e834b8f gl_shader_decompiler: Implement S2R's Y_DIRECTION 2018-11-25 04:37:29 -03:00
bunnei
932fbd5a25 Merge pull request #1791 from bunnei/nvdrv-stub
nvdrv: Implement/stub DumpGraphicsMemoryInfo and GetStatus.
2018-11-24 23:45:24 -05:00
bunnei
7d544c1b9d Merge pull request #1787 from bunnei/fix-gpu-mm
memory_manager: Do not allow 0 to be a valid GPUVAddr.
2018-11-24 23:45:00 -05:00
ReinUsesLisp
7ff2131cf9 morton: Style changes 2018-11-25 00:38:53 -03:00
ReinUsesLisp
dad3a6718e video_core: Move morton functions to their own file 2018-11-25 00:37:18 -03:00
FernandoS27
8c797464a2 Fix Texture Overlapping 2018-11-24 17:26:42 -04:00
FernandoS27
33afff1870 Implemented BRA CC conditional and FSET CC Setting 2018-11-24 13:25:54 -04:00
Rodolfo Bogado
13f6a603c2 Add support for viewport_transfom_enable register 2018-11-24 13:17:48 -03:00
Lioncash
b0df09335c service/sm: Take std::string by const reference in UnregisterService
Avoids the need to create a copy of the std::string instance
(potentially allocating).

The only reason RegisterService takes its argument by value is because
it's std::moved internally.
2018-11-24 00:08:13 -05:00
bunnei
0d673a84b6 nvdrv: Implement/stub DumpGraphicsMemoryInfo and GetStatus.
- Used by Undertale.
2018-11-23 23:22:04 -05:00
FernandoS27
7668ef51d6 Fix TEXS Instruction encodings 2018-11-23 22:46:50 -04:00
FernandoS27
9c2127d5eb Fix one encoding in TEX Instruction 2018-11-23 22:46:49 -04:00
FernandoS27
487d805899 Corrected inputs indexing in TEX instruction 2018-11-23 22:46:48 -04:00
bunnei
0b1842294f memory_manager: Do not allow 0 to be a valid GPUVAddr.
- Fixes a bug with Undertale using 0 for a render target.
2018-11-23 12:58:55 -05:00
ReinUsesLisp
b3853403b7 gl_shader_decompiler: Implement clip distances 2018-11-23 02:14:43 -03:00
greggameplayer
c14af2f71d correct clang-format 2018-11-22 18:26:43 +01:00
greggameplayer
6d2adb0bc0 Automatically disable joycons docked
when docked mode is enable
2018-11-22 01:24:39 +01:00
ReinUsesLisp
642dfeda2a gl_shader_decompiler: Implement BFI_IMM_R 2018-11-21 16:12:30 -03:00
ReinUsesLisp
d92afc7493 gl_shader_decompiler: Implement R2P_IMM 2018-11-21 04:56:00 -03:00
Markus Wick
97f5c4ffd3 gl_rasterizer: Skip VB upload if the state is clean. 2018-11-17 14:28:54 +01:00
149 changed files with 3422 additions and 1898 deletions

View File

@@ -8,7 +8,7 @@
#include "audio_core/codec.h"
#include "common/assert.h"
#include "common/logging/log.h"
#include "core/hle/kernel/event.h"
#include "core/hle/kernel/writable_event.h"
#include "core/memory.h"
namespace AudioCore {
@@ -72,7 +72,7 @@ private:
EffectInStatus info{};
};
AudioRenderer::AudioRenderer(AudioRendererParameter params,
Kernel::SharedPtr<Kernel::Event> buffer_event)
Kernel::SharedPtr<Kernel::WritableEvent> buffer_event)
: worker_params{params}, buffer_event{buffer_event}, voices(params.voice_count),
effects(params.effect_count) {

View File

@@ -15,7 +15,7 @@
#include "core/hle/kernel/object.h"
namespace Kernel {
class Event;
class WritableEvent;
}
namespace AudioCore {
@@ -208,7 +208,8 @@ static_assert(sizeof(UpdateDataHeader) == 0x40, "UpdateDataHeader has wrong size
class AudioRenderer {
public:
AudioRenderer(AudioRendererParameter params, Kernel::SharedPtr<Kernel::Event> buffer_event);
AudioRenderer(AudioRendererParameter params,
Kernel::SharedPtr<Kernel::WritableEvent> buffer_event);
~AudioRenderer();
std::vector<u8> UpdateAudioRenderer(const std::vector<u8>& input_params);
@@ -224,7 +225,7 @@ private:
class VoiceState;
AudioRendererParameter worker_params;
Kernel::SharedPtr<Kernel::Event> buffer_event;
Kernel::SharedPtr<Kernel::WritableEvent> buffer_event;
std::vector<VoiceState> voices;
std::vector<EffectState> effects;
std::unique_ptr<AudioOut> audio_out;

View File

@@ -97,8 +97,6 @@ add_library(core STATIC
hle/kernel/client_session.cpp
hle/kernel/client_session.h
hle/kernel/errors.h
hle/kernel/event.cpp
hle/kernel/event.h
hle/kernel/handle_table.cpp
hle/kernel/handle_table.h
hle/kernel/hle_ipc.cpp
@@ -111,6 +109,8 @@ add_library(core STATIC
hle/kernel/object.h
hle/kernel/process.cpp
hle/kernel/process.h
hle/kernel/readable_event.cpp
hle/kernel/readable_event.h
hle/kernel/resource_limit.cpp
hle/kernel/resource_limit.h
hle/kernel/scheduler.cpp
@@ -133,6 +133,8 @@ add_library(core STATIC
hle/kernel/vm_manager.h
hle/kernel/wait_object.cpp
hle/kernel/wait_object.h
hle/kernel/writable_event.cpp
hle/kernel/writable_event.h
hle/lock.cpp
hle/lock.h
hle/result.h

View File

@@ -794,7 +794,7 @@ void KeyManager::DeriveBase() {
void KeyManager::DeriveETicket(PartitionDataManager& data) {
// ETicket keys
const auto es = Service::FileSystem::GetUnionContents()->GetEntry(
const auto es = Service::FileSystem::GetUnionContents().GetEntry(
0x0100000000000033, FileSys::ContentRecordType::Program);
if (es == nullptr)

View File

@@ -8,13 +8,23 @@
namespace FileSys {
const std::array<const char*, 15> LANGUAGE_NAMES = {
"AmericanEnglish", "BritishEnglish", "Japanese",
"French", "German", "LatinAmericanSpanish",
"Spanish", "Italian", "Dutch",
"CanadianFrench", "Portugese", "Russian",
"Korean", "Taiwanese", "Chinese",
};
const std::array<const char*, 15> LANGUAGE_NAMES{{
"AmericanEnglish",
"BritishEnglish",
"Japanese",
"French",
"German",
"LatinAmericanSpanish",
"Spanish",
"Italian",
"Dutch",
"CanadianFrench",
"Portuguese",
"Russian",
"Korean",
"Taiwanese",
"Chinese",
}};
std::string LanguageEntry::GetApplicationName() const {
return Common::StringFromFixedZeroTerminatedBuffer(application_name.data(),

View File

@@ -75,12 +75,12 @@ VirtualDir PatchManager::PatchExeFS(VirtualDir exefs) const {
// Game Updates
const auto update_tid = GetUpdateTitleID(title_id);
const auto update = installed->GetEntry(update_tid, ContentRecordType::Program);
const auto update = installed.GetEntry(update_tid, ContentRecordType::Program);
if (update != nullptr && update->GetExeFS() != nullptr &&
update->GetStatus() == Loader::ResultStatus::ErrorMissingBKTRBaseRomFS) {
LOG_INFO(Loader, " ExeFS: Update ({}) applied successfully",
FormatTitleVersion(installed->GetEntryVersion(update_tid).value_or(0)));
FormatTitleVersion(installed.GetEntryVersion(update_tid).value_or(0)));
exefs = update->GetExeFS();
}
@@ -281,13 +281,13 @@ VirtualFile PatchManager::PatchRomFS(VirtualFile romfs, u64 ivfc_offset, Content
// Game Updates
const auto update_tid = GetUpdateTitleID(title_id);
const auto update = installed->GetEntryRaw(update_tid, type);
const auto update = installed.GetEntryRaw(update_tid, type);
if (update != nullptr) {
const auto new_nca = std::make_shared<NCA>(update, romfs, ivfc_offset);
if (new_nca->GetStatus() == Loader::ResultStatus::Success &&
new_nca->GetRomFS() != nullptr) {
LOG_INFO(Loader, " RomFS: Update ({}) applied successfully",
FormatTitleVersion(installed->GetEntryVersion(update_tid).value_or(0)));
FormatTitleVersion(installed.GetEntryVersion(update_tid).value_or(0)));
romfs = new_nca->GetRomFS();
}
} else if (update_raw != nullptr) {
@@ -329,8 +329,8 @@ std::map<std::string, std::string, std::less<>> PatchManager::GetPatchVersionNam
if (nacp != nullptr) {
out.insert_or_assign("Update", nacp->GetVersionString());
} else {
if (installed->HasEntry(update_tid, ContentRecordType::Program)) {
const auto meta_ver = installed->GetEntryVersion(update_tid);
if (installed.HasEntry(update_tid, ContentRecordType::Program)) {
const auto meta_ver = installed.GetEntryVersion(update_tid);
if (meta_ver.value_or(0) == 0) {
out.insert_or_assign("Update", "");
} else {
@@ -383,14 +383,13 @@ std::map<std::string, std::string, std::less<>> PatchManager::GetPatchVersionNam
}
// DLC
const auto dlc_entries = installed->ListEntriesFilter(TitleType::AOC, ContentRecordType::Data);
const auto dlc_entries = installed.ListEntriesFilter(TitleType::AOC, ContentRecordType::Data);
std::vector<RegisteredCacheEntry> dlc_match;
dlc_match.reserve(dlc_entries.size());
std::copy_if(dlc_entries.begin(), dlc_entries.end(), std::back_inserter(dlc_match),
[this, &installed](const RegisteredCacheEntry& entry) {
return (entry.title_id & DLC_BASE_TITLE_ID_MASK) == title_id &&
installed->GetEntry(entry)->GetStatus() ==
Loader::ResultStatus::Success;
installed.GetEntry(entry)->GetStatus() == Loader::ResultStatus::Success;
});
if (!dlc_match.empty()) {
// Ensure sorted so DLC IDs show in order.
@@ -411,7 +410,7 @@ std::map<std::string, std::string, std::less<>> PatchManager::GetPatchVersionNam
std::pair<std::unique_ptr<NACP>, VirtualFile> PatchManager::GetControlMetadata() const {
const auto installed{Service::FileSystem::GetUnionContents()};
const auto base_control_nca = installed->GetEntry(title_id, ContentRecordType::Control);
const auto base_control_nca = installed.GetEntry(title_id, ContentRecordType::Control);
if (base_control_nca == nullptr)
return {};

View File

@@ -381,22 +381,22 @@ std::vector<RegisteredCacheEntry> RegisteredCache::ListEntriesFilter(
return out;
}
static std::shared_ptr<NCA> GetNCAFromNSPForID(std::shared_ptr<NSP> nsp, const NcaID& id) {
const auto file = nsp->GetFile(fmt::format("{}.nca", Common::HexArrayToString(id, false)));
static std::shared_ptr<NCA> GetNCAFromNSPForID(const NSP& nsp, const NcaID& id) {
const auto file = nsp.GetFile(fmt::format("{}.nca", Common::HexArrayToString(id, false)));
if (file == nullptr)
return nullptr;
return std::make_shared<NCA>(file);
}
InstallResult RegisteredCache::InstallEntry(std::shared_ptr<XCI> xci, bool overwrite_if_exists,
InstallResult RegisteredCache::InstallEntry(const XCI& xci, bool overwrite_if_exists,
const VfsCopyFunction& copy) {
return InstallEntry(xci->GetSecurePartitionNSP(), overwrite_if_exists, copy);
return InstallEntry(*xci.GetSecurePartitionNSP(), overwrite_if_exists, copy);
}
InstallResult RegisteredCache::InstallEntry(std::shared_ptr<NSP> nsp, bool overwrite_if_exists,
InstallResult RegisteredCache::InstallEntry(const NSP& nsp, bool overwrite_if_exists,
const VfsCopyFunction& copy) {
const auto& ncas = nsp->GetNCAsCollapsed();
const auto& meta_iter = std::find_if(ncas.begin(), ncas.end(), [](std::shared_ptr<NCA> nca) {
const auto ncas = nsp.GetNCAsCollapsed();
const auto meta_iter = std::find_if(ncas.begin(), ncas.end(), [](const auto& nca) {
return nca->GetType() == NCAContentType::Meta;
});
@@ -410,7 +410,7 @@ InstallResult RegisteredCache::InstallEntry(std::shared_ptr<NSP> nsp, bool overw
const auto meta_id_raw = (*meta_iter)->GetName().substr(0, 32);
const auto meta_id = Common::HexStringToArray<16>(meta_id_raw);
const auto res = RawInstallNCA(*meta_iter, copy, overwrite_if_exists, meta_id);
const auto res = RawInstallNCA(**meta_iter, copy, overwrite_if_exists, meta_id);
if (res != InstallResult::Success)
return res;
@@ -422,7 +422,7 @@ InstallResult RegisteredCache::InstallEntry(std::shared_ptr<NSP> nsp, bool overw
const auto nca = GetNCAFromNSPForID(nsp, record.nca_id);
if (nca == nullptr)
return InstallResult::ErrorCopyFailed;
const auto res2 = RawInstallNCA(nca, copy, overwrite_if_exists, record.nca_id);
const auto res2 = RawInstallNCA(*nca, copy, overwrite_if_exists, record.nca_id);
if (res2 != InstallResult::Success)
return res2;
}
@@ -431,21 +431,21 @@ InstallResult RegisteredCache::InstallEntry(std::shared_ptr<NSP> nsp, bool overw
return InstallResult::Success;
}
InstallResult RegisteredCache::InstallEntry(std::shared_ptr<NCA> nca, TitleType type,
InstallResult RegisteredCache::InstallEntry(const NCA& nca, TitleType type,
bool overwrite_if_exists, const VfsCopyFunction& copy) {
CNMTHeader header{
nca->GetTitleId(), ///< Title ID
0, ///< Ignore/Default title version
type, ///< Type
{}, ///< Padding
0x10, ///< Default table offset
1, ///< 1 Content Entry
0, ///< No Meta Entries
{}, ///< Padding
nca.GetTitleId(), ///< Title ID
0, ///< Ignore/Default title version
type, ///< Type
{}, ///< Padding
0x10, ///< Default table offset
1, ///< 1 Content Entry
0, ///< No Meta Entries
{}, ///< Padding
};
OptionalHeader opt_header{0, 0};
ContentRecord c_rec{{}, {}, {}, GetCRTypeFromNCAType(nca->GetType()), {}};
const auto& data = nca->GetBaseFile()->ReadBytes(0x100000);
ContentRecord c_rec{{}, {}, {}, GetCRTypeFromNCAType(nca.GetType()), {}};
const auto& data = nca.GetBaseFile()->ReadBytes(0x100000);
mbedtls_sha256(data.data(), data.size(), c_rec.hash.data(), 0);
memcpy(&c_rec.nca_id, &c_rec.hash, 16);
const CNMT new_cnmt(header, opt_header, {c_rec}, {});
@@ -454,10 +454,10 @@ InstallResult RegisteredCache::InstallEntry(std::shared_ptr<NCA> nca, TitleType
return RawInstallNCA(nca, copy, overwrite_if_exists, c_rec.nca_id);
}
InstallResult RegisteredCache::RawInstallNCA(std::shared_ptr<NCA> nca, const VfsCopyFunction& copy,
InstallResult RegisteredCache::RawInstallNCA(const NCA& nca, const VfsCopyFunction& copy,
bool overwrite_if_exists,
std::optional<NcaID> override_id) {
const auto in = nca->GetBaseFile();
const auto in = nca.GetBaseFile();
Core::Crypto::SHA256Hash hash{};
// Calculate NcaID

View File

@@ -6,7 +6,6 @@
#include <array>
#include <functional>
#include <map>
#include <memory>
#include <string>
#include <vector>
@@ -104,17 +103,16 @@ public:
// Raw copies all the ncas from the xci/nsp to the csache. Does some quick checks to make sure
// there is a meta NCA and all of them are accessible.
InstallResult InstallEntry(std::shared_ptr<XCI> xci, bool overwrite_if_exists = false,
InstallResult InstallEntry(const XCI& xci, bool overwrite_if_exists = false,
const VfsCopyFunction& copy = &VfsRawCopy);
InstallResult InstallEntry(std::shared_ptr<NSP> nsp, bool overwrite_if_exists = false,
InstallResult InstallEntry(const NSP& nsp, bool overwrite_if_exists = false,
const VfsCopyFunction& copy = &VfsRawCopy);
// Due to the fact that we must use Meta-type NCAs to determine the existance of files, this
// poses quite a challenge. Instead of creating a new meta NCA for this file, yuzu will create a
// dir inside the NAND called 'yuzu_meta' and store the raw CNMT there.
// TODO(DarkLordZach): Author real meta-type NCAs and install those.
InstallResult InstallEntry(std::shared_ptr<NCA> nca, TitleType type,
bool overwrite_if_exists = false,
InstallResult InstallEntry(const NCA& nca, TitleType type, bool overwrite_if_exists = false,
const VfsCopyFunction& copy = &VfsRawCopy);
private:
@@ -128,7 +126,7 @@ private:
std::optional<NcaID> GetNcaIDFromMetadata(u64 title_id, ContentRecordType type) const;
VirtualFile GetFileAtID(NcaID id) const;
VirtualFile OpenFileOrDirectoryConcat(const VirtualDir& dir, std::string_view path) const;
InstallResult RawInstallNCA(std::shared_ptr<NCA> nca, const VfsCopyFunction& copy,
InstallResult RawInstallNCA(const NCA& nca, const VfsCopyFunction& copy,
bool overwrite_if_exists, std::optional<NcaID> override_id = {});
bool RawInstallYuzuMeta(const CNMT& cnmt);

View File

@@ -48,7 +48,7 @@ ResultVal<VirtualFile> RomFSFactory::Open(u64 title_id, StorageId storage, Conte
switch (storage) {
case StorageId::None:
res = Service::FileSystem::GetUnionContents()->GetEntry(title_id, type);
res = Service::FileSystem::GetUnionContents().GetEntry(title_id, type);
break;
case StorageId::NandSystem:
res = Service::FileSystem::GetSystemNANDContents()->GetEntry(title_id, type);

View File

@@ -384,6 +384,28 @@ bool VfsDirectory::DeleteSubdirectoryRecursive(std::string_view name) {
return success;
}
bool VfsDirectory::CleanSubdirectoryRecursive(std::string_view name) {
auto dir = GetSubdirectory(name);
if (dir == nullptr) {
return false;
}
bool success = true;
for (const auto& file : dir->GetFiles()) {
if (!dir->DeleteFile(file->GetName())) {
success = false;
}
}
for (const auto& sdir : dir->GetSubdirectories()) {
if (!dir->DeleteSubdirectoryRecursive(sdir->GetName())) {
success = false;
}
}
return success;
}
bool VfsDirectory::Copy(std::string_view src, std::string_view dest) {
const auto f1 = GetFile(src);
auto f2 = CreateFile(dest);
@@ -431,10 +453,34 @@ std::shared_ptr<VfsFile> ReadOnlyVfsDirectory::CreateFile(std::string_view name)
return nullptr;
}
std::shared_ptr<VfsFile> ReadOnlyVfsDirectory::CreateFileAbsolute(std::string_view path) {
return nullptr;
}
std::shared_ptr<VfsFile> ReadOnlyVfsDirectory::CreateFileRelative(std::string_view path) {
return nullptr;
}
std::shared_ptr<VfsDirectory> ReadOnlyVfsDirectory::CreateDirectoryAbsolute(std::string_view path) {
return nullptr;
}
std::shared_ptr<VfsDirectory> ReadOnlyVfsDirectory::CreateDirectoryRelative(std::string_view path) {
return nullptr;
}
bool ReadOnlyVfsDirectory::DeleteSubdirectory(std::string_view name) {
return false;
}
bool ReadOnlyVfsDirectory::DeleteSubdirectoryRecursive(std::string_view name) {
return false;
}
bool ReadOnlyVfsDirectory::CleanSubdirectoryRecursive(std::string_view name) {
return false;
}
bool ReadOnlyVfsDirectory::DeleteFile(std::string_view name) {
return false;
}

View File

@@ -245,12 +245,18 @@ public:
// any failure.
virtual std::shared_ptr<VfsDirectory> CreateDirectoryAbsolute(std::string_view path);
// Deletes the subdirectory with name and returns true on success.
// Deletes the subdirectory with the given name and returns true on success.
virtual bool DeleteSubdirectory(std::string_view name) = 0;
// Deletes all subdirectories and files of subdirectory with name recirsively and then deletes
// the subdirectory. Returns true on success.
// Deletes all subdirectories and files within the provided directory and then deletes
// the directory itself. Returns true on success.
virtual bool DeleteSubdirectoryRecursive(std::string_view name);
// Returnes whether or not the file with name name was deleted successfully.
// Deletes all subdirectories and files within the provided directory.
// Unlike DeleteSubdirectoryRecursive, this does not delete the provided directory.
virtual bool CleanSubdirectoryRecursive(std::string_view name);
// Returns whether or not the file with name name was deleted successfully.
virtual bool DeleteFile(std::string_view name) = 0;
// Returns whether or not this directory was renamed to name.
@@ -276,7 +282,13 @@ public:
bool IsReadable() const override;
std::shared_ptr<VfsDirectory> CreateSubdirectory(std::string_view name) override;
std::shared_ptr<VfsFile> CreateFile(std::string_view name) override;
std::shared_ptr<VfsFile> CreateFileAbsolute(std::string_view path) override;
std::shared_ptr<VfsFile> CreateFileRelative(std::string_view path) override;
std::shared_ptr<VfsDirectory> CreateDirectoryAbsolute(std::string_view path) override;
std::shared_ptr<VfsDirectory> CreateDirectoryRelative(std::string_view path) override;
bool DeleteSubdirectory(std::string_view name) override;
bool DeleteSubdirectoryRecursive(std::string_view name) override;
bool CleanSubdirectoryRecursive(std::string_view name) override;
bool DeleteFile(std::string_view name) override;
bool Rename(std::string_view name) override;
};

View File

@@ -282,7 +282,7 @@ static void FpuWrite(std::size_t id, u128 val, Kernel::Thread* thread = nullptr)
if (id >= UC_ARM64_REG_Q0 && id < FPCR_REGISTER) {
thread_context.vector_registers[id - UC_ARM64_REG_Q0] = val;
} else if (id == FPCR_REGISTER) {
thread_context.fpcr = val[0];
thread_context.fpcr = static_cast<u32>(val[0]);
}
}

View File

@@ -15,13 +15,14 @@
#include "common/logging/log.h"
#include "core/core.h"
#include "core/hle/ipc_helpers.h"
#include "core/hle/kernel/event.h"
#include "core/hle/kernel/handle_table.h"
#include "core/hle/kernel/hle_ipc.h"
#include "core/hle/kernel/kernel.h"
#include "core/hle/kernel/object.h"
#include "core/hle/kernel/process.h"
#include "core/hle/kernel/readable_event.h"
#include "core/hle/kernel/server_session.h"
#include "core/hle/kernel/writable_event.h"
#include "core/memory.h"
namespace Kernel {
@@ -36,11 +37,9 @@ void SessionRequestHandler::ClientDisconnected(const SharedPtr<ServerSession>& s
boost::range::remove_erase(connected_sessions, server_session);
}
SharedPtr<Event> HLERequestContext::SleepClientThread(SharedPtr<Thread> thread,
const std::string& reason, u64 timeout,
WakeupCallback&& callback,
Kernel::SharedPtr<Kernel::Event> event) {
SharedPtr<WritableEvent> HLERequestContext::SleepClientThread(
SharedPtr<Thread> thread, const std::string& reason, u64 timeout, WakeupCallback&& callback,
SharedPtr<WritableEvent> writable_event) {
// Put the client thread to sleep until the wait event is signaled or the timeout expires.
thread->SetWakeupCallback([context = *this, callback](
ThreadWakeupReason reason, SharedPtr<Thread> thread,
@@ -51,23 +50,25 @@ SharedPtr<Event> HLERequestContext::SleepClientThread(SharedPtr<Thread> thread,
return true;
});
if (!event) {
auto& kernel = Core::System::GetInstance().Kernel();
if (!writable_event) {
// Create event if not provided
auto& kernel = Core::System::GetInstance().Kernel();
event =
Kernel::Event::Create(kernel, Kernel::ResetType::OneShot, "HLE Pause Event: " + reason);
const auto pair = WritableEvent::CreateEventPair(kernel, Kernel::ResetType::OneShot,
"HLE Pause Event: " + reason);
writable_event = pair.writable;
}
event->Clear();
const auto readable_event{writable_event->GetReadableEvent()};
writable_event->Clear();
thread->SetStatus(ThreadStatus::WaitHLEEvent);
thread->SetWaitObjects({event});
event->AddWaitingThread(thread);
thread->SetWaitObjects({readable_event});
readable_event->AddWaitingThread(thread);
if (timeout > 0) {
thread->WakeAfterDelay(timeout);
}
return event;
return writable_event;
}
HLERequestContext::HLERequestContext(SharedPtr<Kernel::ServerSession> server_session)

View File

@@ -24,10 +24,11 @@ class ServiceFrameworkBase;
namespace Kernel {
class Domain;
class Event;
class HandleTable;
class HLERequestContext;
class Process;
class ReadableEvent;
class WritableEvent;
/**
* Interface implemented by HLE Session handlers.
@@ -119,12 +120,13 @@ public:
* @param callback Callback to be invoked when the thread is resumed. This callback must write
* the entire command response once again, regardless of the state of it before this function
* was called.
* @param event Event to use to wake up the thread. If unspecified, an event will be created.
* @param writable_event Event to use to wake up the thread. If unspecified, an event will be
* created.
* @returns Event that when signaled will resume the thread and call the callback function.
*/
SharedPtr<Event> SleepClientThread(SharedPtr<Thread> thread, const std::string& reason,
u64 timeout, WakeupCallback&& callback,
Kernel::SharedPtr<Kernel::Event> event = nullptr);
SharedPtr<WritableEvent> SleepClientThread(SharedPtr<Thread> thread, const std::string& reason,
u64 timeout, WakeupCallback&& callback,
SharedPtr<WritableEvent> writable_event = nullptr);
/// Populates this context with data from the requesting process/thread.
ResultCode PopulateFromIncomingCommandBuffer(const HandleTable& handle_table,

View File

@@ -13,7 +13,7 @@ Object::~Object() = default;
bool Object::IsWaitable() const {
switch (GetHandleType()) {
case HandleType::Event:
case HandleType::ReadableEvent:
case HandleType::Thread:
case HandleType::Timer:
case HandleType::ServerPort:
@@ -21,6 +21,7 @@ bool Object::IsWaitable() const {
return true;
case HandleType::Unknown:
case HandleType::WritableEvent:
case HandleType::SharedMemory:
case HandleType::Process:
case HandleType::AddressArbiter:

View File

@@ -19,7 +19,8 @@ using Handle = u32;
enum class HandleType : u32 {
Unknown,
Event,
WritableEvent,
ReadableEvent,
SharedMemory,
Thread,
Process,
@@ -33,9 +34,9 @@ enum class HandleType : u32 {
};
enum class ResetType {
OneShot,
Sticky,
Pulse,
OneShot, ///< Reset automatically on object acquisition
Sticky, ///< Never reset automatically
Pulse, ///< Reset automatically on wakeup
};
class Object : NonCopyable {

View File

@@ -4,46 +4,37 @@
#include <algorithm>
#include "common/assert.h"
#include "core/hle/kernel/event.h"
#include "core/hle/kernel/object.h"
#include "core/hle/kernel/readable_event.h"
#include "core/hle/kernel/thread.h"
#include "core/hle/kernel/writable_event.h"
namespace Kernel {
Event::Event(KernelCore& kernel) : WaitObject{kernel} {}
Event::~Event() = default;
ReadableEvent::ReadableEvent(KernelCore& kernel) : WaitObject{kernel} {}
ReadableEvent::~ReadableEvent() = default;
SharedPtr<Event> Event::Create(KernelCore& kernel, ResetType reset_type, std::string name) {
SharedPtr<Event> evt(new Event(kernel));
evt->signaled = false;
evt->reset_type = reset_type;
evt->name = std::move(name);
return evt;
}
bool Event::ShouldWait(Thread* thread) const {
bool ReadableEvent::ShouldWait(Thread* thread) const {
return !signaled;
}
void Event::Acquire(Thread* thread) {
void ReadableEvent::Acquire(Thread* thread) {
ASSERT_MSG(!ShouldWait(thread), "object unavailable!");
if (reset_type == ResetType::OneShot)
signaled = false;
}
void Event::Signal() {
void ReadableEvent::Signal() {
signaled = true;
WakeupAllWaitingThreads();
}
void Event::Clear() {
void ReadableEvent::Clear() {
signaled = false;
}
void Event::WakeupAllWaitingThreads() {
void ReadableEvent::WakeupAllWaitingThreads() {
WaitObject::WakeupAllWaitingThreads();
if (reset_type == ResetType::Pulse)

View File

@@ -0,0 +1,55 @@
// Copyright 2014 Citra Emulator Project
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#pragma once
#include "core/hle/kernel/object.h"
#include "core/hle/kernel/wait_object.h"
namespace Kernel {
class KernelCore;
class WritableEvent;
class ReadableEvent final : public WaitObject {
friend class WritableEvent;
public:
~ReadableEvent() override;
std::string GetTypeName() const override {
return "ReadableEvent";
}
std::string GetName() const override {
return name;
}
ResetType GetResetType() const {
return reset_type;
}
static const HandleType HANDLE_TYPE = HandleType::ReadableEvent;
HandleType GetHandleType() const override {
return HANDLE_TYPE;
}
bool ShouldWait(Thread* thread) const override;
void Acquire(Thread* thread) override;
void WakeupAllWaitingThreads() override;
void Clear();
private:
explicit ReadableEvent(KernelCore& kernel);
void Signal();
ResetType reset_type;
bool signaled;
std::string name; ///< Name of event (optional)
};
} // namespace Kernel

View File

@@ -14,7 +14,7 @@ namespace Kernel {
class KernelCore;
enum class ResourceType {
enum class ResourceType : u32 {
PhysicalMemory,
Threads,
Events,
@@ -25,6 +25,10 @@ enum class ResourceType {
ResourceTypeCount
};
constexpr bool IsValidResourceType(ResourceType type) {
return type < ResourceType::ResourceTypeCount;
}
class ResourceLimit final : public Object {
public:
/**

File diff suppressed because it is too large Load Diff

View File

@@ -43,6 +43,14 @@ void SvcWrap() {
FuncReturn(func(static_cast<u32>(Param(0)), static_cast<u32>(Param(1))).raw);
}
template <ResultCode func(u32*)>
void SvcWrap() {
u32 param = 0;
const u32 retval = func(&param).raw;
Core::CurrentArmInterface().SetReg(1, param);
FuncReturn(retval);
}
template <ResultCode func(u32*, u32)>
void SvcWrap() {
u32 param_1 = 0;

View File

@@ -0,0 +1,52 @@
// Copyright 2014 Citra Emulator Project
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#include <algorithm>
#include "common/assert.h"
#include "core/hle/kernel/kernel.h"
#include "core/hle/kernel/object.h"
#include "core/hle/kernel/readable_event.h"
#include "core/hle/kernel/thread.h"
#include "core/hle/kernel/writable_event.h"
namespace Kernel {
WritableEvent::WritableEvent(KernelCore& kernel) : Object{kernel} {}
WritableEvent::~WritableEvent() = default;
EventPair WritableEvent::CreateEventPair(KernelCore& kernel, ResetType reset_type,
std::string name) {
SharedPtr<WritableEvent> writable_event(new WritableEvent(kernel));
SharedPtr<ReadableEvent> readable_event(new ReadableEvent(kernel));
writable_event->name = name + ":Writable";
writable_event->readable = readable_event;
readable_event->name = name + ":Readable";
readable_event->signaled = false;
readable_event->reset_type = reset_type;
return {std::move(readable_event), std::move(writable_event)};
}
SharedPtr<ReadableEvent> WritableEvent::GetReadableEvent() const {
return readable;
}
ResetType WritableEvent::GetResetType() const {
return readable->reset_type;
}
void WritableEvent::Signal() {
readable->Signal();
}
void WritableEvent::Clear() {
readable->Clear();
}
bool WritableEvent::IsSignaled() const {
return readable->signaled;
}
} // namespace Kernel

View File

@@ -11,49 +11,52 @@
namespace Kernel {
class KernelCore;
class ReadableEvent;
class WritableEvent;
class Event final : public WaitObject {
struct EventPair {
SharedPtr<ReadableEvent> readable;
SharedPtr<WritableEvent> writable;
};
class WritableEvent final : public Object {
public:
~WritableEvent() override;
/**
* Creates an event
* @param kernel The kernel instance to create this event under.
* @param reset_type ResetType describing how to create event
* @param name Optional name of event
*/
static SharedPtr<Event> Create(KernelCore& kernel, ResetType reset_type,
std::string name = "Unknown");
static EventPair CreateEventPair(KernelCore& kernel, ResetType reset_type,
std::string name = "Unknown");
std::string GetTypeName() const override {
return "Event";
return "WritableEvent";
}
std::string GetName() const override {
return name;
}
static const HandleType HANDLE_TYPE = HandleType::Event;
static const HandleType HANDLE_TYPE = HandleType::WritableEvent;
HandleType GetHandleType() const override {
return HANDLE_TYPE;
}
ResetType GetResetType() const {
return reset_type;
}
SharedPtr<ReadableEvent> GetReadableEvent() const;
bool ShouldWait(Thread* thread) const override;
void Acquire(Thread* thread) override;
void WakeupAllWaitingThreads() override;
ResetType GetResetType() const;
void Signal();
void Clear();
bool IsSignaled() const;
private:
explicit Event(KernelCore& kernel);
~Event() override;
explicit WritableEvent(KernelCore& kernel);
ResetType reset_type; ///< Current ResetType
SharedPtr<ReadableEvent> readable;
bool signaled; ///< Whether the event has already been signaled
std::string name; ///< Name of event (optional)
};

View File

@@ -207,10 +207,11 @@ void Module::Interface::GetLastOpenedUser(Kernel::HLERequestContext& ctx) {
void Module::Interface::GetProfile(Kernel::HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
UUID user_id = rp.PopRaw<UUID>();
LOG_DEBUG(Service_ACC, "called user_id={}", user_id.Format());
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(RESULT_SUCCESS);
rb.PushIpcInterface<IProfile>(user_id, *profile_manager);
LOG_DEBUG(Service_ACC, "called user_id={}", user_id.Format());
}
void Module::Interface::IsUserRegistrationRequestPermitted(Kernel::HLERequestContext& ctx) {
@@ -227,10 +228,10 @@ void Module::Interface::InitializeApplicationInfo(Kernel::HLERequestContext& ctx
}
void Module::Interface::GetBaasAccountManagerForApplication(Kernel::HLERequestContext& ctx) {
LOG_DEBUG(Service_ACC, "called");
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(RESULT_SUCCESS);
rb.PushIpcInterface<IManagerForApplication>();
LOG_DEBUG(Service_ACC, "called");
}
void Module::Interface::TrySelectUserWithoutInteraction(Kernel::HLERequestContext& ctx) {

View File

@@ -9,9 +9,11 @@
#include "audio_core/audio_renderer.h"
#include "core/core.h"
#include "core/hle/ipc_helpers.h"
#include "core/hle/kernel/event.h"
#include "core/hle/kernel/kernel.h"
#include "core/hle/kernel/process.h"
#include "core/hle/kernel/readable_event.h"
#include "core/hle/kernel/shared_memory.h"
#include "core/hle/kernel/writable_event.h"
#include "core/hle/service/acc/profile_manager.h"
#include "core/hle/service/am/am.h"
#include "core/hle/service/am/applet_ae.h"
@@ -208,8 +210,8 @@ ISelfController::ISelfController(std::shared_ptr<NVFlinger::NVFlinger> nvflinger
RegisterHandlers(functions);
auto& kernel = Core::System::GetInstance().Kernel();
launchable_event =
Kernel::Event::Create(kernel, Kernel::ResetType::Sticky, "ISelfController:LaunchableEvent");
launchable_event = Kernel::WritableEvent::CreateEventPair(kernel, Kernel::ResetType::Sticky,
"ISelfController:LaunchableEvent");
}
ISelfController::~ISelfController() = default;
@@ -217,6 +219,7 @@ ISelfController::~ISelfController() = default;
void ISelfController::SetFocusHandlingMode(Kernel::HLERequestContext& ctx) {
// Takes 3 input u8s with each field located immediately after the previous
// u8, these are bool flags. No output.
LOG_WARNING(Service_AM, "(STUBBED) called");
IPC::RequestParser rp{ctx};
@@ -229,44 +232,40 @@ void ISelfController::SetFocusHandlingMode(Kernel::HLERequestContext& ctx) {
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS);
LOG_WARNING(Service_AM, "(STUBBED) called");
}
void ISelfController::SetRestartMessageEnabled(Kernel::HLERequestContext& ctx) {
LOG_WARNING(Service_AM, "(STUBBED) called");
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS);
LOG_WARNING(Service_AM, "(STUBBED) called");
}
void ISelfController::SetPerformanceModeChangedNotification(Kernel::HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
bool flag = rp.Pop<bool>();
LOG_WARNING(Service_AM, "(STUBBED) called flag={}", flag);
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS);
LOG_WARNING(Service_AM, "(STUBBED) called flag={}", flag);
}
void ISelfController::SetScreenShotPermission(Kernel::HLERequestContext& ctx) {
LOG_WARNING(Service_AM, "(STUBBED) called");
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS);
LOG_WARNING(Service_AM, "(STUBBED) called");
}
void ISelfController::SetOperationModeChangedNotification(Kernel::HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
bool flag = rp.Pop<bool>();
LOG_WARNING(Service_AM, "(STUBBED) called flag={}", flag);
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS);
LOG_WARNING(Service_AM, "(STUBBED) called flag={}", flag);
}
void ISelfController::SetOutOfFocusSuspendingEnabled(Kernel::HLERequestContext& ctx) {
@@ -275,45 +274,45 @@ void ISelfController::SetOutOfFocusSuspendingEnabled(Kernel::HLERequestContext&
IPC::RequestParser rp{ctx};
bool enabled = rp.Pop<bool>();
LOG_WARNING(Service_AM, "(STUBBED) called enabled={}", enabled);
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS);
LOG_WARNING(Service_AM, "(STUBBED) called enabled={}", enabled);
}
void ISelfController::LockExit(Kernel::HLERequestContext& ctx) {
LOG_WARNING(Service_AM, "(STUBBED) called");
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS);
LOG_WARNING(Service_AM, "(STUBBED) called");
}
void ISelfController::UnlockExit(Kernel::HLERequestContext& ctx) {
LOG_WARNING(Service_AM, "(STUBBED) called");
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS);
LOG_WARNING(Service_AM, "(STUBBED) called");
}
void ISelfController::GetLibraryAppletLaunchableEvent(Kernel::HLERequestContext& ctx) {
launchable_event->Signal();
LOG_WARNING(Service_AM, "(STUBBED) called");
launchable_event.writable->Signal();
IPC::ResponseBuilder rb{ctx, 2, 1};
rb.Push(RESULT_SUCCESS);
rb.PushCopyObjects(launchable_event);
LOG_WARNING(Service_AM, "(STUBBED) called");
rb.PushCopyObjects(launchable_event.readable);
}
void ISelfController::SetScreenShotImageOrientation(Kernel::HLERequestContext& ctx) {
LOG_WARNING(Service_AM, "(STUBBED) called");
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS);
LOG_WARNING(Service_AM, "(STUBBED) called");
}
void ISelfController::CreateManagedDisplayLayer(Kernel::HLERequestContext& ctx) {
LOG_WARNING(Service_AM, "(STUBBED) called");
// TODO(Subv): Find out how AM determines the display to use, for now just
// create the layer in the Default display.
u64 display_id = nvflinger->OpenDisplay("Default");
@@ -322,66 +321,67 @@ void ISelfController::CreateManagedDisplayLayer(Kernel::HLERequestContext& ctx)
IPC::ResponseBuilder rb{ctx, 4};
rb.Push(RESULT_SUCCESS);
rb.Push(layer_id);
LOG_WARNING(Service_AM, "(STUBBED) called");
}
void ISelfController::SetHandlesRequestToDisplay(Kernel::HLERequestContext& ctx) {
LOG_WARNING(Service_AM, "(STUBBED) called");
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS);
LOG_WARNING(Service_AM, "(STUBBED) called");
}
void ISelfController::SetIdleTimeDetectionExtension(Kernel::HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
idle_time_detection_extension = rp.Pop<u32>();
LOG_WARNING(Service_AM, "(STUBBED) called idle_time_detection_extension={}",
idle_time_detection_extension);
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS);
LOG_WARNING(Service_AM, "(STUBBED) called");
}
void ISelfController::GetIdleTimeDetectionExtension(Kernel::HLERequestContext& ctx) {
LOG_WARNING(Service_AM, "(STUBBED) called");
IPC::ResponseBuilder rb{ctx, 3};
rb.Push(RESULT_SUCCESS);
rb.Push<u32>(idle_time_detection_extension);
LOG_WARNING(Service_AM, "(STUBBED) called");
}
AppletMessageQueue::AppletMessageQueue() {
auto& kernel = Core::System::GetInstance().Kernel();
on_new_message = Kernel::Event::Create(kernel, Kernel::ResetType::Sticky,
"AMMessageQueue:OnMessageRecieved");
on_operation_mode_changed = Kernel::Event::Create(kernel, Kernel::ResetType::OneShot,
"AMMessageQueue:OperationModeChanged");
on_new_message = Kernel::WritableEvent::CreateEventPair(kernel, Kernel::ResetType::Sticky,
"AMMessageQueue:OnMessageRecieved");
on_operation_mode_changed = Kernel::WritableEvent::CreateEventPair(
kernel, Kernel::ResetType::OneShot, "AMMessageQueue:OperationModeChanged");
}
AppletMessageQueue::~AppletMessageQueue() = default;
const Kernel::SharedPtr<Kernel::Event>& AppletMessageQueue::GetMesssageRecieveEvent() const {
return on_new_message;
const Kernel::SharedPtr<Kernel::ReadableEvent>& AppletMessageQueue::GetMesssageRecieveEvent()
const {
return on_new_message.readable;
}
const Kernel::SharedPtr<Kernel::Event>& AppletMessageQueue::GetOperationModeChangedEvent() const {
return on_operation_mode_changed;
const Kernel::SharedPtr<Kernel::ReadableEvent>& AppletMessageQueue::GetOperationModeChangedEvent()
const {
return on_operation_mode_changed.readable;
}
void AppletMessageQueue::PushMessage(AppletMessage msg) {
messages.push(msg);
on_new_message->Signal();
on_new_message.writable->Signal();
}
AppletMessageQueue::AppletMessage AppletMessageQueue::PopMessage() {
if (messages.empty()) {
on_new_message->Clear();
on_new_message.writable->Clear();
return AppletMessage::NoMessage;
}
auto msg = messages.front();
messages.pop();
if (messages.empty()) {
on_new_message->Clear();
on_new_message.writable->Clear();
}
return msg;
}
@@ -393,7 +393,7 @@ std::size_t AppletMessageQueue::GetMessageCount() const {
void AppletMessageQueue::OperationModeChanged() {
PushMessage(AppletMessage::OperationModeChanged);
PushMessage(AppletMessage::PerformanceModeChanged);
on_operation_mode_changed->Signal();
on_operation_mode_changed.writable->Signal();
}
ICommonStateGetter::ICommonStateGetter(std::shared_ptr<AppletMessageQueue> msg_queue)
@@ -430,55 +430,54 @@ ICommonStateGetter::ICommonStateGetter(std::shared_ptr<AppletMessageQueue> msg_q
// clang-format on
RegisterHandlers(functions);
auto& kernel = Core::System::GetInstance().Kernel();
event = Kernel::Event::Create(kernel, Kernel::ResetType::OneShot, "ICommonStateGetter:Event");
}
ICommonStateGetter::~ICommonStateGetter() = default;
void ICommonStateGetter::GetBootMode(Kernel::HLERequestContext& ctx) {
LOG_DEBUG(Service_AM, "called");
IPC::ResponseBuilder rb{ctx, 3};
rb.Push(RESULT_SUCCESS);
rb.Push<u8>(static_cast<u8>(Service::PM::SystemBootMode::Normal)); // Normal boot mode
LOG_DEBUG(Service_AM, "called");
}
void ICommonStateGetter::GetEventHandle(Kernel::HLERequestContext& ctx) {
LOG_DEBUG(Service_AM, "called");
IPC::ResponseBuilder rb{ctx, 2, 1};
rb.Push(RESULT_SUCCESS);
rb.PushCopyObjects(msg_queue->GetMesssageRecieveEvent());
LOG_DEBUG(Service_AM, "called");
}
void ICommonStateGetter::ReceiveMessage(Kernel::HLERequestContext& ctx) {
LOG_DEBUG(Service_AM, "called");
IPC::ResponseBuilder rb{ctx, 3};
rb.Push(RESULT_SUCCESS);
rb.PushEnum<AppletMessageQueue::AppletMessage>(msg_queue->PopMessage());
LOG_DEBUG(Service_AM, "called");
}
void ICommonStateGetter::GetCurrentFocusState(Kernel::HLERequestContext& ctx) {
LOG_WARNING(Service_AM, "(STUBBED) called");
IPC::ResponseBuilder rb{ctx, 3};
rb.Push(RESULT_SUCCESS);
rb.Push(static_cast<u8>(FocusState::InFocus));
LOG_WARNING(Service_AM, "(STUBBED) called");
}
void ICommonStateGetter::GetDefaultDisplayResolutionChangeEvent(Kernel::HLERequestContext& ctx) {
LOG_DEBUG(Service_AM, "called");
IPC::ResponseBuilder rb{ctx, 2, 1};
rb.Push(RESULT_SUCCESS);
rb.PushCopyObjects(msg_queue->GetOperationModeChangedEvent());
LOG_DEBUG(Service_AM, "called");
}
void ICommonStateGetter::GetDefaultDisplayResolution(Kernel::HLERequestContext& ctx) {
LOG_DEBUG(Service_AM, "called");
IPC::ResponseBuilder rb{ctx, 4};
rb.Push(RESULT_SUCCESS);
@@ -493,8 +492,6 @@ void ICommonStateGetter::GetDefaultDisplayResolution(Kernel::HLERequestContext&
rb.Push(static_cast<u32>(Service::VI::DisplayResolution::UndockedHeight) *
static_cast<u32>(Settings::values.resolution_factor));
}
LOG_DEBUG(Service_AM, "called");
}
IStorage::IStorage(std::vector<u8> buffer)
@@ -517,21 +514,21 @@ const std::vector<u8>& IStorage::GetData() const {
void ICommonStateGetter::GetOperationMode(Kernel::HLERequestContext& ctx) {
const bool use_docked_mode{Settings::values.use_docked_mode};
LOG_DEBUG(Service_AM, "called, use_docked_mode={}", use_docked_mode);
IPC::ResponseBuilder rb{ctx, 3};
rb.Push(RESULT_SUCCESS);
rb.Push(static_cast<u8>(use_docked_mode ? OperationMode::Docked : OperationMode::Handheld));
LOG_DEBUG(Service_AM, "called");
}
void ICommonStateGetter::GetPerformanceMode(Kernel::HLERequestContext& ctx) {
const bool use_docked_mode{Settings::values.use_docked_mode};
LOG_DEBUG(Service_AM, "called, use_docked_mode={}", use_docked_mode);
IPC::ResponseBuilder rb{ctx, 3};
rb.Push(RESULT_SUCCESS);
rb.Push(static_cast<u32>(use_docked_mode ? APM::PerformanceMode::Docked
: APM::PerformanceMode::Handheld));
LOG_DEBUG(Service_AM, "called");
}
class ILibraryAppletAccessor final : public ServiceFramework<ILibraryAppletAccessor> {
@@ -566,32 +563,34 @@ public:
private:
void GetAppletStateChangedEvent(Kernel::HLERequestContext& ctx) {
LOG_DEBUG(Service_AM, "called");
applet->GetBroker().SignalStateChanged();
const auto event = applet->GetBroker().GetStateChangedEvent();
event->Signal();
IPC::ResponseBuilder rb{ctx, 2, 1};
rb.Push(RESULT_SUCCESS);
rb.PushCopyObjects(event);
LOG_DEBUG(Service_AM, "called");
}
void IsCompleted(Kernel::HLERequestContext& ctx) {
LOG_DEBUG(Service_AM, "called");
IPC::ResponseBuilder rb{ctx, 3};
rb.Push(RESULT_SUCCESS);
rb.Push<u32>(applet->TransactionComplete());
LOG_DEBUG(Service_AM, "called");
}
void GetResult(Kernel::HLERequestContext& ctx) {
LOG_DEBUG(Service_AM, "called");
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(applet->GetStatus());
LOG_DEBUG(Service_AM, "called");
}
void Start(Kernel::HLERequestContext& ctx) {
LOG_DEBUG(Service_AM, "called");
ASSERT(applet != nullptr);
applet->Initialize();
@@ -599,36 +598,39 @@ private:
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS);
LOG_DEBUG(Service_AM, "called");
}
void PushInData(Kernel::HLERequestContext& ctx) {
LOG_DEBUG(Service_AM, "called");
IPC::RequestParser rp{ctx};
applet->GetBroker().PushNormalDataFromGame(*rp.PopIpcInterface<IStorage>());
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS);
LOG_DEBUG(Service_AM, "called");
}
void PopOutData(Kernel::HLERequestContext& ctx) {
LOG_DEBUG(Service_AM, "called");
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
const auto storage = applet->GetBroker().PopNormalDataToGame();
if (storage == nullptr) {
LOG_ERROR(Service_AM,
"storage is a nullptr. There is no data in the current normal channel");
rb.Push(ERR_NO_DATA_IN_CHANNEL);
return;
}
rb.Push(RESULT_SUCCESS);
rb.PushIpcInterface<IStorage>(std::move(*storage));
LOG_DEBUG(Service_AM, "called");
}
void PushInteractiveInData(Kernel::HLERequestContext& ctx) {
LOG_DEBUG(Service_AM, "called");
IPC::RequestParser rp{ctx};
applet->GetBroker().PushInteractiveDataFromGame(*rp.PopIpcInterface<IStorage>());
@@ -638,51 +640,52 @@ private:
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS);
LOG_DEBUG(Service_AM, "called");
}
void PopInteractiveOutData(Kernel::HLERequestContext& ctx) {
LOG_DEBUG(Service_AM, "called");
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
const auto storage = applet->GetBroker().PopInteractiveDataToGame();
if (storage == nullptr) {
LOG_ERROR(Service_AM,
"storage is a nullptr. There is no data in the current interactive channel");
rb.Push(ERR_NO_DATA_IN_CHANNEL);
return;
}
rb.Push(RESULT_SUCCESS);
rb.PushIpcInterface<IStorage>(std::move(*storage));
LOG_DEBUG(Service_AM, "called");
}
void GetPopOutDataEvent(Kernel::HLERequestContext& ctx) {
LOG_DEBUG(Service_AM, "called");
IPC::ResponseBuilder rb{ctx, 2, 1};
rb.Push(RESULT_SUCCESS);
rb.PushCopyObjects(applet->GetBroker().GetNormalDataEvent());
LOG_DEBUG(Service_AM, "called");
}
void GetPopInteractiveOutDataEvent(Kernel::HLERequestContext& ctx) {
LOG_DEBUG(Service_AM, "called");
IPC::ResponseBuilder rb{ctx, 2, 1};
rb.Push(RESULT_SUCCESS);
rb.PushCopyObjects(applet->GetBroker().GetInteractiveDataEvent());
LOG_DEBUG(Service_AM, "called");
}
std::shared_ptr<Applets::Applet> applet;
};
void IStorage::Open(Kernel::HLERequestContext& ctx) {
LOG_DEBUG(Service_AM, "called");
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(RESULT_SUCCESS);
rb.PushIpcInterface<IStorageAccessor>(*this);
LOG_DEBUG(Service_AM, "called");
}
IStorageAccessor::IStorageAccessor(IStorage& storage)
@@ -701,21 +704,27 @@ IStorageAccessor::IStorageAccessor(IStorage& storage)
IStorageAccessor::~IStorageAccessor() = default;
void IStorageAccessor::GetSize(Kernel::HLERequestContext& ctx) {
LOG_DEBUG(Service_AM, "called");
IPC::ResponseBuilder rb{ctx, 4};
rb.Push(RESULT_SUCCESS);
rb.Push(static_cast<u64>(backing.buffer.size()));
LOG_DEBUG(Service_AM, "called");
}
void IStorageAccessor::Write(Kernel::HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
const u64 offset{rp.Pop<u64>()};
LOG_DEBUG(Service_AM, "called, offset={}", offset);
const std::vector<u8> data{ctx.ReadBuffer()};
if (data.size() > backing.buffer.size() - offset) {
LOG_ERROR(Service_AM,
"offset is out of bounds, backing_buffer_sz={}, data_size={}, offset={}",
backing.buffer.size(), data.size(), offset);
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(ERR_SIZE_OUT_OF_BOUNDS);
}
@@ -724,17 +733,20 @@ void IStorageAccessor::Write(Kernel::HLERequestContext& ctx) {
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS);
LOG_DEBUG(Service_AM, "called, offset={}", offset);
}
void IStorageAccessor::Read(Kernel::HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
const u64 offset{rp.Pop<u64>()};
LOG_DEBUG(Service_AM, "called, offset={}", offset);
const std::size_t size{ctx.GetWriteBufferSize()};
if (size > backing.buffer.size() - offset) {
LOG_ERROR(Service_AM, "offset is out of bounds, backing_buffer_sz={}, size={}, offset={}",
backing.buffer.size(), size, offset);
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(ERR_SIZE_OUT_OF_BOUNDS);
}
@@ -743,8 +755,6 @@ void IStorageAccessor::Read(Kernel::HLERequestContext& ctx) {
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS);
LOG_DEBUG(Service_AM, "called, offset={}", offset);
}
ILibraryAppletCreator::ILibraryAppletCreator() : ServiceFramework("ILibraryAppletCreator") {
@@ -783,6 +793,8 @@ void ILibraryAppletCreator::CreateLibraryApplet(Kernel::HLERequestContext& ctx)
const auto applet = GetAppletFromId(applet_id);
if (applet == nullptr) {
LOG_ERROR(Service_AM, "Applet doesn't exist! applet_id={}", static_cast<u32>(applet_id));
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(ResultCode(-1));
return;
@@ -792,23 +804,23 @@ void ILibraryAppletCreator::CreateLibraryApplet(Kernel::HLERequestContext& ctx)
rb.Push(RESULT_SUCCESS);
rb.PushIpcInterface<AM::ILibraryAppletAccessor>(applet);
LOG_DEBUG(Service_AM, "called");
}
void ILibraryAppletCreator::CreateStorage(Kernel::HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
const u64 size{rp.Pop<u64>()};
LOG_DEBUG(Service_AM, "called, size={}", size);
std::vector<u8> buffer(size);
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(RESULT_SUCCESS);
rb.PushIpcInterface<AM::IStorage>(std::move(buffer));
LOG_DEBUG(Service_AM, "called, size={}", size);
}
void ILibraryAppletCreator::CreateTransferMemoryStorage(Kernel::HLERequestContext& ctx) {
LOG_DEBUG(Service_AM, "called");
IPC::RequestParser rp{ctx};
rp.SetCurrentOffset(3);
@@ -819,6 +831,7 @@ void ILibraryAppletCreator::CreateTransferMemoryStorage(Kernel::HLERequestContex
handle);
if (shared_mem == nullptr) {
LOG_ERROR(Service_AM, "shared_mem is a nullpr for handle={:08X}", handle);
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(ResultCode(-1));
return;
@@ -882,38 +895,45 @@ IApplicationFunctions::IApplicationFunctions() : ServiceFramework("IApplicationF
IApplicationFunctions::~IApplicationFunctions() = default;
void IApplicationFunctions::EnableApplicationCrashReport(Kernel::HLERequestContext& ctx) {
LOG_WARNING(Service_AM, "(STUBBED) called");
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS);
LOG_WARNING(Service_AM, "(STUBBED) called");
}
void IApplicationFunctions::BeginBlockingHomeButtonShortAndLongPressed(
Kernel::HLERequestContext& ctx) {
LOG_WARNING(Service_AM, "(STUBBED) called");
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS);
LOG_WARNING(Service_AM, "(STUBBED) called");
}
void IApplicationFunctions::EndBlockingHomeButtonShortAndLongPressed(
Kernel::HLERequestContext& ctx) {
LOG_WARNING(Service_AM, "(STUBBED) called");
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS);
LOG_WARNING(Service_AM, "(STUBBED) called");
}
void IApplicationFunctions::BeginBlockingHomeButton(Kernel::HLERequestContext& ctx) {
LOG_WARNING(Service_AM, "(STUBBED) called");
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS);
LOG_WARNING(Service_AM, "(STUBBED) called");
}
void IApplicationFunctions::EndBlockingHomeButton(Kernel::HLERequestContext& ctx) {
LOG_WARNING(Service_AM, "(STUBBED) called");
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS);
LOG_WARNING(Service_AM, "(STUBBED) called");
}
void IApplicationFunctions::PopLaunchParameter(Kernel::HLERequestContext& ctx) {
LOG_DEBUG(Service_AM, "called");
LaunchParameters params{};
params.magic = POP_LAUNCH_PARAMETER_MAGIC;
@@ -932,21 +952,19 @@ void IApplicationFunctions::PopLaunchParameter(Kernel::HLERequestContext& ctx) {
std::memcpy(buffer.data(), &params, buffer.size());
rb.PushIpcInterface<AM::IStorage>(buffer);
LOG_DEBUG(Service_AM, "called");
}
void IApplicationFunctions::CreateApplicationAndRequestToStartForQuest(
Kernel::HLERequestContext& ctx) {
LOG_WARNING(Service_AM, "(STUBBED) called");
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS);
LOG_WARNING(Service_AM, "(STUBBED) called");
}
void IApplicationFunctions::EnsureSaveData(Kernel::HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
u128 uid = rp.PopRaw<u128>(); // What does this do?
LOG_WARNING(Service, "(STUBBED) called uid = {:016X}{:016X}", uid[1], uid[0]);
IPC::ResponseBuilder rb{ctx, 4};
@@ -961,60 +979,62 @@ void IApplicationFunctions::SetTerminateResult(Kernel::HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
u32 result = rp.Pop<u32>();
LOG_WARNING(Service_AM, "(STUBBED) called, result=0x{:08X}", result);
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS);
LOG_WARNING(Service_AM, "(STUBBED) called, result=0x{:08X}", result);
}
void IApplicationFunctions::GetDisplayVersion(Kernel::HLERequestContext& ctx) {
LOG_WARNING(Service_AM, "(STUBBED) called");
IPC::ResponseBuilder rb{ctx, 6};
rb.Push(RESULT_SUCCESS);
rb.Push<u64>(1);
rb.Push<u64>(0);
LOG_WARNING(Service_AM, "(STUBBED) called");
}
void IApplicationFunctions::GetDesiredLanguage(Kernel::HLERequestContext& ctx) {
// TODO(bunnei): This should be configurable
LOG_DEBUG(Service_AM, "called");
IPC::ResponseBuilder rb{ctx, 4};
rb.Push(RESULT_SUCCESS);
rb.Push(
static_cast<u64>(Service::Set::GetLanguageCodeFromIndex(Settings::values.language_index)));
LOG_DEBUG(Service_AM, "called");
}
void IApplicationFunctions::InitializeGamePlayRecording(Kernel::HLERequestContext& ctx) {
LOG_WARNING(Service_AM, "(STUBBED) called");
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS);
LOG_WARNING(Service_AM, "(STUBBED) called");
}
void IApplicationFunctions::SetGamePlayRecordingState(Kernel::HLERequestContext& ctx) {
LOG_WARNING(Service_AM, "(STUBBED) called");
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS);
LOG_WARNING(Service_AM, "(STUBBED) called");
}
void IApplicationFunctions::NotifyRunning(Kernel::HLERequestContext& ctx) {
LOG_WARNING(Service_AM, "(STUBBED) called");
IPC::ResponseBuilder rb{ctx, 3};
rb.Push(RESULT_SUCCESS);
rb.Push<u8>(0); // Unknown, seems to be ignored by official processes
LOG_WARNING(Service_AM, "(STUBBED) called");
}
void IApplicationFunctions::GetPseudoDeviceId(Kernel::HLERequestContext& ctx) {
LOG_WARNING(Service_AM, "(STUBBED) called");
IPC::ResponseBuilder rb{ctx, 6};
rb.Push(RESULT_SUCCESS);
// Returns a 128-bit UUID
rb.Push<u64>(0);
rb.Push<u64>(0);
LOG_WARNING(Service_AM, "(STUBBED) called");
}
void InstallInterfaces(SM::ServiceManager& service_manager,
@@ -1051,9 +1071,10 @@ IHomeMenuFunctions::IHomeMenuFunctions() : ServiceFramework("IHomeMenuFunctions"
IHomeMenuFunctions::~IHomeMenuFunctions() = default;
void IHomeMenuFunctions::RequestToGetForeground(Kernel::HLERequestContext& ctx) {
LOG_WARNING(Service_AM, "(STUBBED) called");
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS);
LOG_WARNING(Service_AM, "(STUBBED) called");
}
IGlobalStateController::IGlobalStateController() : ServiceFramework("IGlobalStateController") {

View File

@@ -6,12 +6,9 @@
#include <memory>
#include <queue>
#include "core/hle/kernel/writable_event.h"
#include "core/hle/service/service.h"
namespace Kernel {
class Event;
}
namespace Service {
namespace NVFlinger {
class NVFlinger;
@@ -52,8 +49,8 @@ public:
AppletMessageQueue();
~AppletMessageQueue();
const Kernel::SharedPtr<Kernel::Event>& GetMesssageRecieveEvent() const;
const Kernel::SharedPtr<Kernel::Event>& GetOperationModeChangedEvent() const;
const Kernel::SharedPtr<Kernel::ReadableEvent>& GetMesssageRecieveEvent() const;
const Kernel::SharedPtr<Kernel::ReadableEvent>& GetOperationModeChangedEvent() const;
void PushMessage(AppletMessage msg);
AppletMessage PopMessage();
std::size_t GetMessageCount() const;
@@ -61,8 +58,8 @@ public:
private:
std::queue<AppletMessage> messages;
Kernel::SharedPtr<Kernel::Event> on_new_message;
Kernel::SharedPtr<Kernel::Event> on_operation_mode_changed;
Kernel::EventPair on_new_message;
Kernel::EventPair on_operation_mode_changed;
};
class IWindowController final : public ServiceFramework<IWindowController> {
@@ -122,7 +119,7 @@ private:
void GetIdleTimeDetectionExtension(Kernel::HLERequestContext& ctx);
std::shared_ptr<NVFlinger::NVFlinger> nvflinger;
Kernel::SharedPtr<Kernel::Event> launchable_event;
Kernel::EventPair launchable_event;
u32 idle_time_detection_extension = 0;
};
@@ -151,7 +148,6 @@ private:
void GetBootMode(Kernel::HLERequestContext& ctx);
void GetDefaultDisplayResolution(Kernel::HLERequestContext& ctx);
Kernel::SharedPtr<Kernel::Event> event;
std::shared_ptr<AppletMessageQueue> msg_queue;
};

View File

@@ -32,66 +32,75 @@ public:
private:
void GetCommonStateGetter(Kernel::HLERequestContext& ctx) {
LOG_DEBUG(Service_AM, "called");
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(RESULT_SUCCESS);
rb.PushIpcInterface<ICommonStateGetter>(msg_queue);
LOG_DEBUG(Service_AM, "called");
}
void GetSelfController(Kernel::HLERequestContext& ctx) {
LOG_DEBUG(Service_AM, "called");
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(RESULT_SUCCESS);
rb.PushIpcInterface<ISelfController>(nvflinger);
LOG_DEBUG(Service_AM, "called");
}
void GetWindowController(Kernel::HLERequestContext& ctx) {
LOG_DEBUG(Service_AM, "called");
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(RESULT_SUCCESS);
rb.PushIpcInterface<IWindowController>();
LOG_DEBUG(Service_AM, "called");
}
void GetAudioController(Kernel::HLERequestContext& ctx) {
LOG_DEBUG(Service_AM, "called");
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(RESULT_SUCCESS);
rb.PushIpcInterface<IAudioController>();
LOG_DEBUG(Service_AM, "called");
}
void GetDisplayController(Kernel::HLERequestContext& ctx) {
LOG_DEBUG(Service_AM, "called");
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(RESULT_SUCCESS);
rb.PushIpcInterface<IDisplayController>();
LOG_DEBUG(Service_AM, "called");
}
void GetProcessWindingController(Kernel::HLERequestContext& ctx) {
LOG_DEBUG(Service_AM, "called");
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(RESULT_SUCCESS);
rb.PushIpcInterface<IProcessWindingController>();
LOG_DEBUG(Service_AM, "called");
}
void GetDebugFunctions(Kernel::HLERequestContext& ctx) {
LOG_DEBUG(Service_AM, "called");
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(RESULT_SUCCESS);
rb.PushIpcInterface<IDebugFunctions>();
LOG_DEBUG(Service_AM, "called");
}
void GetLibraryAppletCreator(Kernel::HLERequestContext& ctx) {
LOG_DEBUG(Service_AM, "called");
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(RESULT_SUCCESS);
rb.PushIpcInterface<ILibraryAppletCreator>();
LOG_DEBUG(Service_AM, "called");
}
void GetApplicationFunctions(Kernel::HLERequestContext& ctx) {
LOG_DEBUG(Service_AM, "called");
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(RESULT_SUCCESS);
rb.PushIpcInterface<IApplicationFunctions>();
LOG_DEBUG(Service_AM, "called");
}
std::shared_ptr<NVFlinger::NVFlinger> nvflinger;
@@ -122,97 +131,110 @@ public:
private:
void GetCommonStateGetter(Kernel::HLERequestContext& ctx) {
LOG_DEBUG(Service_AM, "called");
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(RESULT_SUCCESS);
rb.PushIpcInterface<ICommonStateGetter>(msg_queue);
LOG_DEBUG(Service_AM, "called");
}
void GetSelfController(Kernel::HLERequestContext& ctx) {
LOG_DEBUG(Service_AM, "called");
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(RESULT_SUCCESS);
rb.PushIpcInterface<ISelfController>(nvflinger);
LOG_DEBUG(Service_AM, "called");
}
void GetWindowController(Kernel::HLERequestContext& ctx) {
LOG_DEBUG(Service_AM, "called");
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(RESULT_SUCCESS);
rb.PushIpcInterface<IWindowController>();
LOG_DEBUG(Service_AM, "called");
}
void GetAudioController(Kernel::HLERequestContext& ctx) {
LOG_DEBUG(Service_AM, "called");
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(RESULT_SUCCESS);
rb.PushIpcInterface<IAudioController>();
LOG_DEBUG(Service_AM, "called");
}
void GetDisplayController(Kernel::HLERequestContext& ctx) {
LOG_DEBUG(Service_AM, "called");
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(RESULT_SUCCESS);
rb.PushIpcInterface<IDisplayController>();
LOG_DEBUG(Service_AM, "called");
}
void GetDebugFunctions(Kernel::HLERequestContext& ctx) {
LOG_DEBUG(Service_AM, "called");
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(RESULT_SUCCESS);
rb.PushIpcInterface<IDebugFunctions>();
LOG_DEBUG(Service_AM, "called");
}
void GetLibraryAppletCreator(Kernel::HLERequestContext& ctx) {
LOG_DEBUG(Service_AM, "called");
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(RESULT_SUCCESS);
rb.PushIpcInterface<ILibraryAppletCreator>();
LOG_DEBUG(Service_AM, "called");
}
void GetHomeMenuFunctions(Kernel::HLERequestContext& ctx) {
LOG_DEBUG(Service_AM, "called");
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(RESULT_SUCCESS);
rb.PushIpcInterface<IHomeMenuFunctions>();
LOG_DEBUG(Service_AM, "called");
}
void GetGlobalStateController(Kernel::HLERequestContext& ctx) {
LOG_DEBUG(Service_AM, "called");
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(RESULT_SUCCESS);
rb.PushIpcInterface<IGlobalStateController>();
LOG_DEBUG(Service_AM, "called");
}
void GetApplicationCreator(Kernel::HLERequestContext& ctx) {
LOG_DEBUG(Service_AM, "called");
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(RESULT_SUCCESS);
rb.PushIpcInterface<IApplicationCreator>();
LOG_DEBUG(Service_AM, "called");
}
std::shared_ptr<NVFlinger::NVFlinger> nvflinger;
std::shared_ptr<AppletMessageQueue> msg_queue;
};
void AppletAE::OpenSystemAppletProxy(Kernel::HLERequestContext& ctx) {
LOG_DEBUG(Service_AM, "called");
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(RESULT_SUCCESS);
rb.PushIpcInterface<ISystemAppletProxy>(nvflinger, msg_queue);
LOG_DEBUG(Service_AM, "called");
}
void AppletAE::OpenLibraryAppletProxy(Kernel::HLERequestContext& ctx) {
LOG_DEBUG(Service_AM, "called");
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(RESULT_SUCCESS);
rb.PushIpcInterface<ILibraryAppletProxy>(nvflinger, msg_queue);
LOG_DEBUG(Service_AM, "called");
}
void AppletAE::OpenLibraryAppletProxyOld(Kernel::HLERequestContext& ctx) {
LOG_DEBUG(Service_AM, "called");
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(RESULT_SUCCESS);
rb.PushIpcInterface<ILibraryAppletProxy>(nvflinger, msg_queue);
LOG_DEBUG(Service_AM, "called");
}
AppletAE::AppletAE(std::shared_ptr<NVFlinger::NVFlinger> nvflinger,

View File

@@ -35,59 +35,67 @@ public:
private:
void GetAudioController(Kernel::HLERequestContext& ctx) {
LOG_DEBUG(Service_AM, "called");
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(RESULT_SUCCESS);
rb.PushIpcInterface<IAudioController>();
LOG_DEBUG(Service_AM, "called");
}
void GetDisplayController(Kernel::HLERequestContext& ctx) {
LOG_DEBUG(Service_AM, "called");
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(RESULT_SUCCESS);
rb.PushIpcInterface<IDisplayController>();
LOG_DEBUG(Service_AM, "called");
}
void GetDebugFunctions(Kernel::HLERequestContext& ctx) {
LOG_DEBUG(Service_AM, "called");
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(RESULT_SUCCESS);
rb.PushIpcInterface<IDebugFunctions>();
LOG_DEBUG(Service_AM, "called");
}
void GetWindowController(Kernel::HLERequestContext& ctx) {
LOG_DEBUG(Service_AM, "called");
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(RESULT_SUCCESS);
rb.PushIpcInterface<IWindowController>();
LOG_DEBUG(Service_AM, "called");
}
void GetSelfController(Kernel::HLERequestContext& ctx) {
LOG_DEBUG(Service_AM, "called");
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(RESULT_SUCCESS);
rb.PushIpcInterface<ISelfController>(nvflinger);
LOG_DEBUG(Service_AM, "called");
}
void GetCommonStateGetter(Kernel::HLERequestContext& ctx) {
LOG_DEBUG(Service_AM, "called");
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(RESULT_SUCCESS);
rb.PushIpcInterface<ICommonStateGetter>(msg_queue);
LOG_DEBUG(Service_AM, "called");
}
void GetLibraryAppletCreator(Kernel::HLERequestContext& ctx) {
LOG_DEBUG(Service_AM, "called");
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(RESULT_SUCCESS);
rb.PushIpcInterface<ILibraryAppletCreator>();
LOG_DEBUG(Service_AM, "called");
}
void GetApplicationFunctions(Kernel::HLERequestContext& ctx) {
LOG_DEBUG(Service_AM, "called");
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(RESULT_SUCCESS);
rb.PushIpcInterface<IApplicationFunctions>();
LOG_DEBUG(Service_AM, "called");
}
std::shared_ptr<NVFlinger::NVFlinger> nvflinger;
@@ -95,10 +103,11 @@ private:
};
void AppletOE::OpenApplicationProxy(Kernel::HLERequestContext& ctx) {
LOG_DEBUG(Service_AM, "called");
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(RESULT_SUCCESS);
rb.PushIpcInterface<IApplicationProxy>(nvflinger, msg_queue);
LOG_DEBUG(Service_AM, "called");
}
AppletOE::AppletOE(std::shared_ptr<NVFlinger::NVFlinger> nvflinger,

View File

@@ -5,8 +5,9 @@
#include <cstring>
#include "common/assert.h"
#include "core/core.h"
#include "core/hle/kernel/event.h"
#include "core/hle/kernel/readable_event.h"
#include "core/hle/kernel/server_port.h"
#include "core/hle/kernel/writable_event.h"
#include "core/hle/service/am/am.h"
#include "core/hle/service/am/applets/applets.h"
@@ -14,11 +15,11 @@ namespace Service::AM::Applets {
AppletDataBroker::AppletDataBroker() {
auto& kernel = Core::System::GetInstance().Kernel();
state_changed_event = Kernel::Event::Create(kernel, Kernel::ResetType::OneShot,
"ILibraryAppletAccessor:StateChangedEvent");
pop_out_data_event = Kernel::Event::Create(kernel, Kernel::ResetType::OneShot,
"ILibraryAppletAccessor:PopDataOutEvent");
pop_interactive_out_data_event = Kernel::Event::Create(
state_changed_event = Kernel::WritableEvent::CreateEventPair(
kernel, Kernel::ResetType::OneShot, "ILibraryAppletAccessor:StateChangedEvent");
pop_out_data_event = Kernel::WritableEvent::CreateEventPair(
kernel, Kernel::ResetType::OneShot, "ILibraryAppletAccessor:PopDataOutEvent");
pop_interactive_out_data_event = Kernel::WritableEvent::CreateEventPair(
kernel, Kernel::ResetType::OneShot, "ILibraryAppletAccessor:PopInteractiveDataOutEvent");
}
@@ -66,7 +67,7 @@ void AppletDataBroker::PushNormalDataFromGame(IStorage storage) {
void AppletDataBroker::PushNormalDataFromApplet(IStorage storage) {
out_channel.push(std::make_unique<IStorage>(storage));
pop_out_data_event->Signal();
pop_out_data_event.writable->Signal();
}
void AppletDataBroker::PushInteractiveDataFromGame(IStorage storage) {
@@ -75,23 +76,23 @@ void AppletDataBroker::PushInteractiveDataFromGame(IStorage storage) {
void AppletDataBroker::PushInteractiveDataFromApplet(IStorage storage) {
out_interactive_channel.push(std::make_unique<IStorage>(storage));
pop_interactive_out_data_event->Signal();
pop_interactive_out_data_event.writable->Signal();
}
void AppletDataBroker::SignalStateChanged() const {
state_changed_event->Signal();
state_changed_event.writable->Signal();
}
Kernel::SharedPtr<Kernel::Event> AppletDataBroker::GetNormalDataEvent() const {
return pop_out_data_event;
Kernel::SharedPtr<Kernel::ReadableEvent> AppletDataBroker::GetNormalDataEvent() const {
return pop_out_data_event.readable;
}
Kernel::SharedPtr<Kernel::Event> AppletDataBroker::GetInteractiveDataEvent() const {
return pop_interactive_out_data_event;
Kernel::SharedPtr<Kernel::ReadableEvent> AppletDataBroker::GetInteractiveDataEvent() const {
return pop_interactive_out_data_event.readable;
}
Kernel::SharedPtr<Kernel::Event> AppletDataBroker::GetStateChangedEvent() const {
return state_changed_event;
Kernel::SharedPtr<Kernel::ReadableEvent> AppletDataBroker::GetStateChangedEvent() const {
return state_changed_event.readable;
}
Applet::Applet() = default;

View File

@@ -8,13 +8,10 @@
#include <queue>
#include "common/swap.h"
#include "core/hle/kernel/kernel.h"
#include "core/hle/kernel/writable_event.h"
union ResultCode;
namespace Kernel {
class Event;
}
namespace Service::AM {
class IStorage;
@@ -40,9 +37,9 @@ public:
void SignalStateChanged() const;
Kernel::SharedPtr<Kernel::Event> GetNormalDataEvent() const;
Kernel::SharedPtr<Kernel::Event> GetInteractiveDataEvent() const;
Kernel::SharedPtr<Kernel::Event> GetStateChangedEvent() const;
Kernel::SharedPtr<Kernel::ReadableEvent> GetNormalDataEvent() const;
Kernel::SharedPtr<Kernel::ReadableEvent> GetInteractiveDataEvent() const;
Kernel::SharedPtr<Kernel::ReadableEvent> GetStateChangedEvent() const;
private:
// Queues are named from applet's perspective
@@ -59,13 +56,13 @@ private:
// PopInteractiveDataToGame and PushInteractiveDataFromApplet
std::queue<std::unique_ptr<IStorage>> out_interactive_channel;
Kernel::SharedPtr<Kernel::Event> state_changed_event;
Kernel::EventPair state_changed_event;
// Signaled on PushNormalDataFromApplet
Kernel::SharedPtr<Kernel::Event> pop_out_data_event;
Kernel::EventPair pop_out_data_event;
// Signaled on PushInteractiveDataFromApplet
Kernel::SharedPtr<Kernel::Event> pop_interactive_out_data_event;
Kernel::EventPair pop_interactive_out_data_event;
};
class Applet {

View File

@@ -13,8 +13,10 @@
#include "core/file_sys/patch_manager.h"
#include "core/file_sys/registered_cache.h"
#include "core/hle/ipc_helpers.h"
#include "core/hle/kernel/event.h"
#include "core/hle/kernel/kernel.h"
#include "core/hle/kernel/process.h"
#include "core/hle/kernel/readable_event.h"
#include "core/hle/kernel/writable_event.h"
#include "core/hle/service/aoc/aoc_u.h"
#include "core/hle/service/filesystem/filesystem.h"
#include "core/loader/loader.h"
@@ -32,14 +34,14 @@ static std::vector<u64> AccumulateAOCTitleIDs() {
std::vector<u64> add_on_content;
const auto rcu = FileSystem::GetUnionContents();
const auto list =
rcu->ListEntriesFilter(FileSys::TitleType::AOC, FileSys::ContentRecordType::Data);
rcu.ListEntriesFilter(FileSys::TitleType::AOC, FileSys::ContentRecordType::Data);
std::transform(list.begin(), list.end(), std::back_inserter(add_on_content),
[](const FileSys::RegisteredCacheEntry& rce) { return rce.title_id; });
add_on_content.erase(
std::remove_if(
add_on_content.begin(), add_on_content.end(),
[&rcu](u64 tid) {
return rcu->GetEntry(tid, FileSys::ContentRecordType::Data)->GetStatus() !=
return rcu.GetEntry(tid, FileSys::ContentRecordType::Data)->GetStatus() !=
Loader::ResultStatus::Success;
}),
add_on_content.end());
@@ -61,13 +63,15 @@ AOC_U::AOC_U() : ServiceFramework("aoc:u"), add_on_content(AccumulateAOCTitleIDs
RegisterHandlers(functions);
auto& kernel = Core::System::GetInstance().Kernel();
aoc_change_event = Kernel::Event::Create(kernel, Kernel::ResetType::Sticky,
"GetAddOnContentListChanged:Event");
aoc_change_event = Kernel::WritableEvent::CreateEventPair(kernel, Kernel::ResetType::Sticky,
"GetAddOnContentListChanged:Event");
}
AOC_U::~AOC_U() = default;
void AOC_U::CountAddOnContent(Kernel::HLERequestContext& ctx) {
LOG_DEBUG(Service_AOC, "called");
IPC::ResponseBuilder rb{ctx, 3};
rb.Push(RESULT_SUCCESS);
@@ -82,6 +86,7 @@ void AOC_U::ListAddOnContent(Kernel::HLERequestContext& ctx) {
const auto offset = rp.PopRaw<u32>();
auto count = rp.PopRaw<u32>();
LOG_DEBUG(Service_AOC, "called with offset={}, count={}", offset, count);
const auto current = Core::System::GetInstance().CurrentProcess()->GetTitleID();
@@ -110,6 +115,8 @@ void AOC_U::ListAddOnContent(Kernel::HLERequestContext& ctx) {
}
void AOC_U::GetAddOnContentBaseId(Kernel::HLERequestContext& ctx) {
LOG_DEBUG(Service_AOC, "called");
IPC::ResponseBuilder rb{ctx, 4};
rb.Push(RESULT_SUCCESS);
const auto title_id = Core::System::GetInstance().CurrentProcess()->GetTitleID();
@@ -128,7 +135,6 @@ void AOC_U::PrepareAddOnContent(Kernel::HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
const auto aoc_id = rp.PopRaw<u32>();
LOG_WARNING(Service_AOC, "(STUBBED) called with aoc_id={:08X}", aoc_id);
IPC::ResponseBuilder rb{ctx, 2};
@@ -140,7 +146,7 @@ void AOC_U::GetAddOnContentListChangedEvent(Kernel::HLERequestContext& ctx) {
IPC::ResponseBuilder rb{ctx, 2, 1};
rb.Push(RESULT_SUCCESS);
rb.PushCopyObjects(aoc_change_event);
rb.PushCopyObjects(aoc_change_event.readable);
}
void InstallInterfaces(SM::ServiceManager& service_manager) {

View File

@@ -6,6 +6,10 @@
#include "core/hle/service/service.h"
namespace Kernel {
class WritableEvent;
}
namespace Service::AOC {
class AOC_U final : public ServiceFramework<AOC_U> {
@@ -21,7 +25,7 @@ private:
void GetAddOnContentListChangedEvent(Kernel::HLERequestContext& ctx);
std::vector<u64> add_on_content;
Kernel::SharedPtr<Kernel::Event> aoc_change_event;
Kernel::EventPair aoc_change_event;
};
/// Registers all AOC services with the specified service manager.

View File

@@ -40,24 +40,22 @@ private:
auto mode = static_cast<PerformanceMode>(rp.Pop<u32>());
u32 config = rp.Pop<u32>();
LOG_WARNING(Service_APM, "(STUBBED) called mode={} config={}", static_cast<u32>(mode),
config);
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS);
LOG_WARNING(Service_APM, "(STUBBED) called mode={} config={}", static_cast<u32>(mode),
config);
}
void GetPerformanceConfiguration(Kernel::HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
auto mode = static_cast<PerformanceMode>(rp.Pop<u32>());
LOG_WARNING(Service_APM, "(STUBBED) called mode={}", static_cast<u32>(mode));
IPC::ResponseBuilder rb{ctx, 3};
rb.Push(RESULT_SUCCESS);
rb.Push<u32>(static_cast<u32>(PerformanceConfiguration::Config1));
LOG_WARNING(Service_APM, "(STUBBED) called mode={}", static_cast<u32>(mode));
}
};
@@ -73,11 +71,11 @@ APM::APM(std::shared_ptr<Module> apm, const char* name)
APM::~APM() = default;
void APM::OpenSession(Kernel::HLERequestContext& ctx) {
LOG_DEBUG(Service_APM, "called");
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(RESULT_SUCCESS);
rb.PushIpcInterface<ISession>();
LOG_DEBUG(Service_APM, "called");
}
APM_Sys::APM_Sys() : ServiceFramework{"apm:sys"} {
@@ -98,11 +96,11 @@ APM_Sys::APM_Sys() : ServiceFramework{"apm:sys"} {
APM_Sys::~APM_Sys() = default;
void APM_Sys::GetPerformanceEvent(Kernel::HLERequestContext& ctx) {
LOG_DEBUG(Service_APM, "called");
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(RESULT_SUCCESS);
rb.PushIpcInterface<ISession>();
LOG_DEBUG(Service_APM, "called");
}
} // namespace Service::APM

View File

@@ -59,11 +59,11 @@ public:
private:
void AcquireRegistrar(Kernel::HLERequestContext& ctx) {
LOG_DEBUG(Service_ARP, "called");
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(RESULT_SUCCESS);
rb.PushIpcInterface<IRegistrar>();
LOG_DEBUG(Service_ARP, "called");
}
};

View File

@@ -13,8 +13,10 @@
#include "common/swap.h"
#include "core/core.h"
#include "core/hle/ipc_helpers.h"
#include "core/hle/kernel/event.h"
#include "core/hle/kernel/hle_ipc.h"
#include "core/hle/kernel/kernel.h"
#include "core/hle/kernel/readable_event.h"
#include "core/hle/kernel/writable_event.h"
#include "core/hle/service/audio/audout_u.h"
#include "core/memory.h"
@@ -46,8 +48,8 @@ class IAudioOut final : public ServiceFramework<IAudioOut> {
public:
IAudioOut(AudoutParams audio_params, AudioCore::AudioOut& audio_core, std::string&& device_name,
std::string&& unique_name)
: ServiceFramework("IAudioOut"), audio_core(audio_core), audio_params(audio_params),
device_name(std::move(device_name)) {
: ServiceFramework("IAudioOut"), audio_core(audio_core),
device_name(std::move(device_name)), audio_params(audio_params) {
static const FunctionInfo functions[] = {
{0, &IAudioOut::GetAudioOutState, "GetAudioOutState"},
@@ -67,11 +69,12 @@ public:
// This is the event handle used to check if the audio buffer was released
auto& kernel = Core::System::GetInstance().Kernel();
buffer_event =
Kernel::Event::Create(kernel, Kernel::ResetType::Sticky, "IAudioOutBufferReleased");
buffer_event = Kernel::WritableEvent::CreateEventPair(kernel, Kernel::ResetType::Sticky,
"IAudioOutBufferReleased");
stream = audio_core.OpenStream(audio_params.sample_rate, audio_params.channel_count,
std::move(unique_name), [=]() { buffer_event->Signal(); });
std::move(unique_name),
[=]() { buffer_event.writable->Signal(); });
}
private:
@@ -86,6 +89,7 @@ private:
void GetAudioOutState(Kernel::HLERequestContext& ctx) {
LOG_DEBUG(Service_Audio, "called");
IPC::ResponseBuilder rb{ctx, 3};
rb.Push(RESULT_SUCCESS);
rb.Push(static_cast<u32>(stream->IsPlaying() ? AudioState::Started : AudioState::Stopped));
@@ -120,7 +124,7 @@ private:
IPC::ResponseBuilder rb{ctx, 2, 1};
rb.Push(RESULT_SUCCESS);
rb.PushCopyObjects(buffer_event);
rb.PushCopyObjects(buffer_event.readable);
}
void AppendAudioOutBufferImpl(Kernel::HLERequestContext& ctx) {
@@ -148,6 +152,7 @@ private:
void GetReleasedAudioOutBufferImpl(Kernel::HLERequestContext& ctx) {
LOG_DEBUG(Service_Audio, "called {}", ctx.Description());
IPC::RequestParser rp{ctx};
const u64 max_count{ctx.GetWriteBufferSize() / sizeof(u64)};
const auto released_buffers{audio_core.GetTagsAndReleaseBuffers(stream, max_count)};
@@ -163,6 +168,7 @@ private:
void ContainsAudioOutBuffer(Kernel::HLERequestContext& ctx) {
LOG_DEBUG(Service_Audio, "called");
IPC::RequestParser rp{ctx};
const u64 tag{rp.Pop<u64>()};
IPC::ResponseBuilder rb{ctx, 3};
@@ -172,6 +178,7 @@ private:
void GetAudioOutBufferCount(Kernel::HLERequestContext& ctx) {
LOG_DEBUG(Service_Audio, "called");
IPC::ResponseBuilder rb{ctx, 3};
rb.Push(RESULT_SUCCESS);
rb.Push(static_cast<u32>(stream->GetQueueSize()));
@@ -183,12 +190,13 @@ private:
AudoutParams audio_params{};
/// This is the evend handle used to check if the audio buffer was released
Kernel::SharedPtr<Kernel::Event> buffer_event;
/// This is the event handle used to check if the audio buffer was released
Kernel::EventPair buffer_event;
};
void AudOutU::ListAudioOutsImpl(Kernel::HLERequestContext& ctx) {
LOG_DEBUG(Service_Audio, "called");
IPC::RequestParser rp{ctx};
ctx.WriteBuffer(DefaultDevice);

View File

@@ -12,8 +12,10 @@
#include "common/logging/log.h"
#include "core/core.h"
#include "core/hle/ipc_helpers.h"
#include "core/hle/kernel/event.h"
#include "core/hle/kernel/hle_ipc.h"
#include "core/hle/kernel/kernel.h"
#include "core/hle/kernel/readable_event.h"
#include "core/hle/kernel/writable_event.h"
#include "core/hle/service/audio/audren_u.h"
namespace Service::Audio {
@@ -41,85 +43,90 @@ public:
RegisterHandlers(functions);
auto& kernel = Core::System::GetInstance().Kernel();
system_event =
Kernel::Event::Create(kernel, Kernel::ResetType::Sticky, "IAudioRenderer:SystemEvent");
renderer = std::make_unique<AudioCore::AudioRenderer>(audren_params, system_event);
system_event = Kernel::WritableEvent::CreateEventPair(kernel, Kernel::ResetType::Sticky,
"IAudioRenderer:SystemEvent");
renderer = std::make_unique<AudioCore::AudioRenderer>(audren_params, system_event.writable);
}
private:
void UpdateAudioCallback() {
system_event->Signal();
system_event.writable->Signal();
}
void GetSampleRate(Kernel::HLERequestContext& ctx) {
LOG_DEBUG(Service_Audio, "called");
IPC::ResponseBuilder rb{ctx, 3};
rb.Push(RESULT_SUCCESS);
rb.Push<u32>(renderer->GetSampleRate());
LOG_DEBUG(Service_Audio, "called");
}
void GetSampleCount(Kernel::HLERequestContext& ctx) {
LOG_DEBUG(Service_Audio, "called");
IPC::ResponseBuilder rb{ctx, 3};
rb.Push(RESULT_SUCCESS);
rb.Push<u32>(renderer->GetSampleCount());
LOG_DEBUG(Service_Audio, "called");
}
void GetState(Kernel::HLERequestContext& ctx) {
LOG_DEBUG(Service_Audio, "called");
IPC::ResponseBuilder rb{ctx, 3};
rb.Push(RESULT_SUCCESS);
rb.Push<u32>(static_cast<u32>(renderer->GetStreamState()));
LOG_DEBUG(Service_Audio, "called");
}
void GetMixBufferCount(Kernel::HLERequestContext& ctx) {
LOG_DEBUG(Service_Audio, "called");
IPC::ResponseBuilder rb{ctx, 3};
rb.Push(RESULT_SUCCESS);
rb.Push<u32>(renderer->GetMixBufferCount());
LOG_DEBUG(Service_Audio, "called");
}
void RequestUpdateImpl(Kernel::HLERequestContext& ctx) {
LOG_WARNING(Service_Audio, "(STUBBED) called");
ctx.WriteBuffer(renderer->UpdateAudioRenderer(ctx.ReadBuffer()));
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS);
LOG_WARNING(Service_Audio, "(STUBBED) called");
}
void Start(Kernel::HLERequestContext& ctx) {
LOG_WARNING(Service_Audio, "(STUBBED) called");
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS);
LOG_WARNING(Service_Audio, "(STUBBED) called");
}
void Stop(Kernel::HLERequestContext& ctx) {
LOG_WARNING(Service_Audio, "(STUBBED) called");
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS);
LOG_WARNING(Service_Audio, "(STUBBED) called");
}
void QuerySystemEvent(Kernel::HLERequestContext& ctx) {
LOG_WARNING(Service_Audio, "(STUBBED) called");
IPC::ResponseBuilder rb{ctx, 2, 1};
rb.Push(RESULT_SUCCESS);
rb.PushCopyObjects(system_event);
LOG_WARNING(Service_Audio, "(STUBBED) called");
rb.PushCopyObjects(system_event.readable);
}
void SetRenderingTimeLimit(Kernel::HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
rendering_time_limit_percent = rp.Pop<u32>();
LOG_DEBUG(Service_Audio, "called. rendering_time_limit_percent={}",
rendering_time_limit_percent);
ASSERT(rendering_time_limit_percent >= 0 && rendering_time_limit_percent <= 100);
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS);
LOG_DEBUG(Service_Audio, "called. rendering_time_limit_percent={}",
rendering_time_limit_percent);
}
void GetRenderingTimeLimit(Kernel::HLERequestContext& ctx) {
@@ -130,7 +137,7 @@ private:
rb.Push(rendering_time_limit_percent);
}
Kernel::SharedPtr<Kernel::Event> system_event;
Kernel::EventPair system_event;
std::unique_ptr<AudioCore::AudioRenderer> renderer;
u32 rendering_time_limit_percent = 100;
};
@@ -157,8 +164,8 @@ public:
RegisterHandlers(functions);
auto& kernel = Core::System::GetInstance().Kernel();
buffer_event = Kernel::Event::Create(kernel, Kernel::ResetType::OneShot,
"IAudioOutBufferReleasedEvent");
buffer_event = Kernel::WritableEvent::CreateEventPair(kernel, Kernel::ResetType::OneShot,
"IAudioOutBufferReleasedEvent");
}
private:
@@ -202,21 +209,22 @@ private:
void QueryAudioDeviceSystemEvent(Kernel::HLERequestContext& ctx) {
LOG_WARNING(Service_Audio, "(STUBBED) called");
buffer_event->Signal();
buffer_event.writable->Signal();
IPC::ResponseBuilder rb{ctx, 2, 1};
rb.Push(RESULT_SUCCESS);
rb.PushCopyObjects(buffer_event);
rb.PushCopyObjects(buffer_event.readable);
}
void GetActiveChannelCount(Kernel::HLERequestContext& ctx) {
LOG_WARNING(Service_Audio, "(STUBBED) called");
IPC::ResponseBuilder rb{ctx, 3};
rb.Push(RESULT_SUCCESS);
rb.Push<u32>(1);
}
Kernel::SharedPtr<Kernel::Event> buffer_event;
Kernel::EventPair buffer_event;
}; // namespace Audio
@@ -235,19 +243,20 @@ AudRenU::AudRenU() : ServiceFramework("audren:u") {
AudRenU::~AudRenU() = default;
void AudRenU::OpenAudioRenderer(Kernel::HLERequestContext& ctx) {
LOG_DEBUG(Service_Audio, "called");
IPC::RequestParser rp{ctx};
auto params = rp.PopRaw<AudioCore::AudioRendererParameter>();
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(RESULT_SUCCESS);
rb.PushIpcInterface<Audio::IAudioRenderer>(std::move(params));
LOG_DEBUG(Service_Audio, "called");
}
void AudRenU::GetAudioRendererWorkBufferSize(Kernel::HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
auto params = rp.PopRaw<AudioCore::AudioRendererParameter>();
LOG_DEBUG(Service_Audio, "called");
u64 buffer_sz = Common::AlignUp(4 * params.mix_buffer_count, 0x40);
buffer_sz += params.unknown_c * 1024;
@@ -301,26 +310,26 @@ void AudRenU::GetAudioRendererWorkBufferSize(Kernel::HLERequestContext& ctx) {
rb.Push(RESULT_SUCCESS);
rb.Push<u64>(output_sz);
LOG_DEBUG(Service_Audio, "called, buffer_size=0x{:X}", output_sz);
LOG_DEBUG(Service_Audio, "buffer_size=0x{:X}", output_sz);
}
void AudRenU::GetAudioDevice(Kernel::HLERequestContext& ctx) {
LOG_DEBUG(Service_Audio, "called");
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(RESULT_SUCCESS);
rb.PushIpcInterface<Audio::IAudioDevice>();
LOG_DEBUG(Service_Audio, "called");
}
void AudRenU::GetAudioDeviceServiceWithRevisionInfo(Kernel::HLERequestContext& ctx) {
LOG_WARNING(Service_Audio, "(STUBBED) called");
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(RESULT_SUCCESS);
rb.PushIpcInterface<Audio::IAudioDevice>();
LOG_WARNING(Service_Audio, "(STUBBED) called"); // TODO(ogniK): Figure out what is different
// based on the current revision
rb.PushIpcInterface<Audio::IAudioDevice>(); // TODO(ogniK): Figure out what is different
// based on the current revision
}
bool AudRenU::IsFeatureSupported(AudioFeatures feature, u32_le revision) const {

View File

@@ -46,10 +46,13 @@ public:
private:
void DecodeInterleaved(Kernel::HLERequestContext& ctx) {
LOG_DEBUG(Audio, "called");
u32 consumed = 0;
u32 sample_count = 0;
std::vector<opus_int16> samples(ctx.GetWriteBufferSize() / sizeof(opus_int16));
if (!Decoder_DecodeInterleaved(consumed, sample_count, ctx.ReadBuffer(), samples)) {
LOG_ERROR(Audio, "Failed to decode opus data");
IPC::ResponseBuilder rb{ctx, 2};
// TODO(ogniK): Use correct error code
rb.Push(ResultCode(-1));
@@ -63,12 +66,15 @@ private:
}
void DecodeInterleavedWithPerformance(Kernel::HLERequestContext& ctx) {
LOG_DEBUG(Audio, "called");
u32 consumed = 0;
u32 sample_count = 0;
u64 performance = 0;
std::vector<opus_int16> samples(ctx.GetWriteBufferSize() / sizeof(opus_int16));
if (!Decoder_DecodeInterleaved(consumed, sample_count, ctx.ReadBuffer(), samples,
performance)) {
LOG_ERROR(Audio, "Failed to decode opus data");
IPC::ResponseBuilder rb{ctx, 2};
// TODO(ogniK): Use correct error code
rb.Push(ResultCode(-1));
@@ -88,24 +94,39 @@ private:
std::optional<std::reference_wrapper<u64>> performance_time = std::nullopt) {
const auto start_time = std::chrono::high_resolution_clock::now();
std::size_t raw_output_sz = output.size() * sizeof(opus_int16);
if (sizeof(OpusHeader) > input.size())
if (sizeof(OpusHeader) > input.size()) {
LOG_ERROR(Audio, "Input is smaller than the header size, header_sz={}, input_sz={}",
sizeof(OpusHeader), input.size());
return false;
}
OpusHeader hdr{};
std::memcpy(&hdr, input.data(), sizeof(OpusHeader));
if (sizeof(OpusHeader) + static_cast<u32>(hdr.sz) > input.size()) {
LOG_ERROR(Audio, "Input does not fit in the opus header size. data_sz={}, input_sz={}",
sizeof(OpusHeader) + static_cast<u32>(hdr.sz), input.size());
return false;
}
auto frame = input.data() + sizeof(OpusHeader);
auto decoded_sample_count = opus_packet_get_nb_samples(
frame, static_cast<opus_int32>(input.size() - sizeof(OpusHeader)),
static_cast<opus_int32>(sample_rate));
if (decoded_sample_count * channel_count * sizeof(u16) > raw_output_sz)
if (decoded_sample_count * channel_count * sizeof(u16) > raw_output_sz) {
LOG_ERROR(
Audio,
"Decoded data does not fit into the output data, decoded_sz={}, raw_output_sz={}",
decoded_sample_count * channel_count * sizeof(u16), raw_output_sz);
return false;
}
const int frame_size = (static_cast<int>(raw_output_sz / sizeof(s16) / channel_count));
auto out_sample_count =
opus_decode(decoder.get(), frame, hdr.sz, output.data(),
(static_cast<int>(raw_output_sz / sizeof(s16) / channel_count)), 0);
if (out_sample_count < 0)
opus_decode(decoder.get(), frame, hdr.sz, output.data(), frame_size, 0);
if (out_sample_count < 0) {
LOG_ERROR(Audio,
"Incorrect sample count received from opus_decode, "
"output_sample_count={}, frame_size={}, data_sz_from_hdr={}",
out_sample_count, frame_size, static_cast<u32>(hdr.sz));
return false;
}
const auto end_time = std::chrono::high_resolution_clock::now() - start_time;
sample_count = out_sample_count;
consumed = static_cast<u32>(sizeof(OpusHeader) + hdr.sz);
@@ -134,14 +155,17 @@ static std::size_t WorkerBufferSize(u32 channel_count) {
void HwOpus::GetWorkBufferSize(Kernel::HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
auto sample_rate = rp.Pop<u32>();
auto channel_count = rp.Pop<u32>();
const auto sample_rate = rp.Pop<u32>();
const auto channel_count = rp.Pop<u32>();
LOG_DEBUG(Audio, "called with sample_rate={}, channel_count={}", sample_rate, channel_count);
ASSERT_MSG(sample_rate == 48000 || sample_rate == 24000 || sample_rate == 16000 ||
sample_rate == 12000 || sample_rate == 8000,
"Invalid sample rate");
ASSERT_MSG(channel_count == 1 || channel_count == 2, "Invalid channel count");
u32 worker_buffer_sz = static_cast<u32>(WorkerBufferSize(channel_count));
LOG_DEBUG(Audio, "called worker_buffer_sz={}", worker_buffer_sz);
const u32 worker_buffer_sz = static_cast<u32>(WorkerBufferSize(channel_count));
LOG_DEBUG(Audio, "worker_buffer_sz={}", worker_buffer_sz);
IPC::ResponseBuilder rb{ctx, 3};
rb.Push(RESULT_SUCCESS);
@@ -155,6 +179,7 @@ void HwOpus::OpenOpusDecoder(Kernel::HLERequestContext& ctx) {
auto buffer_sz = rp.Pop<u32>();
LOG_DEBUG(Audio, "called sample_rate={}, channel_count={}, buffer_size={}", sample_rate,
channel_count, buffer_sz);
ASSERT_MSG(sample_rate == 48000 || sample_rate == 24000 || sample_rate == 16000 ||
sample_rate == 12000 || sample_rate == 8000,
"Invalid sample rate");
@@ -164,7 +189,8 @@ void HwOpus::OpenOpusDecoder(Kernel::HLERequestContext& ctx) {
ASSERT_MSG(buffer_sz >= worker_sz, "Worker buffer too large");
std::unique_ptr<OpusDecoder, OpusDeleter> decoder{
static_cast<OpusDecoder*>(operator new(worker_sz))};
if (opus_decoder_init(decoder.get(), sample_rate, channel_count)) {
if (const int err = opus_decoder_init(decoder.get(), sample_rate, channel_count)) {
LOG_ERROR(Audio, "Failed to init opus decoder with error={}", err);
IPC::ResponseBuilder rb{ctx, 2};
// TODO(ogniK): Use correct error code
rb.Push(ResultCode(-1));

View File

@@ -33,10 +33,11 @@ public:
};
void Module::Interface::CreateBcatService(Kernel::HLERequestContext& ctx) {
LOG_DEBUG(Service_BCAT, "called");
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(RESULT_SUCCESS);
rb.PushIpcInterface<IBcatService>();
LOG_DEBUG(Service_BCAT, "called");
}
Module::Interface::Interface(std::shared_ptr<Module> module, const char* name)

View File

@@ -4,8 +4,10 @@
#include "common/logging/log.h"
#include "core/hle/ipc_helpers.h"
#include "core/hle/kernel/event.h"
#include "core/hle/kernel/hle_ipc.h"
#include "core/hle/kernel/kernel.h"
#include "core/hle/kernel/readable_event.h"
#include "core/hle/kernel/writable_event.h"
#include "core/hle/service/btdrv/btdrv.h"
#include "core/hle/service/service.h"
#include "core/hle/service/sm/sm.h"
@@ -30,19 +32,22 @@ public:
};
// clang-format on
RegisterHandlers(functions);
auto& kernel = Core::System::GetInstance().Kernel();
register_event = Kernel::WritableEvent::CreateEventPair(kernel, Kernel::ResetType::OneShot,
"BT:RegisterEvent");
}
private:
void RegisterEvent(Kernel::HLERequestContext& ctx) {
auto& kernel = Core::System::GetInstance().Kernel();
register_event =
Kernel::Event::Create(kernel, Kernel::ResetType::OneShot, "BT:RegisterEvent");
LOG_WARNING(Service_BTM, "(STUBBED) called");
IPC::ResponseBuilder rb{ctx, 2, 1};
rb.Push(RESULT_SUCCESS);
rb.PushCopyObjects(register_event);
LOG_WARNING(Service_BTM, "(STUBBED) called");
rb.PushCopyObjects(register_event.readable);
}
Kernel::SharedPtr<Kernel::Event> register_event;
Kernel::EventPair register_event;
};
class BtDrv final : public ServiceFramework<BtDrv> {

View File

@@ -6,8 +6,10 @@
#include "common/logging/log.h"
#include "core/hle/ipc_helpers.h"
#include "core/hle/kernel/event.h"
#include "core/hle/kernel/hle_ipc.h"
#include "core/hle/kernel/kernel.h"
#include "core/hle/kernel/readable_event.h"
#include "core/hle/kernel/writable_event.h"
#include "core/hle/service/btm/btm.h"
#include "core/hle/service/service.h"
@@ -53,49 +55,55 @@ public:
};
// clang-format on
RegisterHandlers(functions);
auto& kernel = Core::System::GetInstance().Kernel();
scan_event = Kernel::WritableEvent::CreateEventPair(kernel, Kernel::ResetType::OneShot,
"IBtmUserCore:ScanEvent");
connection_event = Kernel::WritableEvent::CreateEventPair(
kernel, Kernel::ResetType::OneShot, "IBtmUserCore:ConnectionEvent");
service_discovery = Kernel::WritableEvent::CreateEventPair(
kernel, Kernel::ResetType::OneShot, "IBtmUserCore:Discovery");
config_event = Kernel::WritableEvent::CreateEventPair(kernel, Kernel::ResetType::OneShot,
"IBtmUserCore:ConfigEvent");
}
private:
void GetScanEvent(Kernel::HLERequestContext& ctx) {
auto& kernel = Core::System::GetInstance().Kernel();
scan_event =
Kernel::Event::Create(kernel, Kernel::ResetType::OneShot, "IBtmUserCore:ScanEvent");
LOG_WARNING(Service_BTM, "(STUBBED) called");
IPC::ResponseBuilder rb{ctx, 2, 1};
rb.Push(RESULT_SUCCESS);
rb.PushCopyObjects(scan_event);
LOG_WARNING(Service_BTM, "(STUBBED) called");
rb.PushCopyObjects(scan_event.readable);
}
void GetConnectionEvent(Kernel::HLERequestContext& ctx) {
auto& kernel = Core::System::GetInstance().Kernel();
connection_event = Kernel::Event::Create(kernel, Kernel::ResetType::OneShot,
"IBtmUserCore:ConnectionEvent");
LOG_WARNING(Service_BTM, "(STUBBED) called");
IPC::ResponseBuilder rb{ctx, 2, 1};
rb.Push(RESULT_SUCCESS);
rb.PushCopyObjects(connection_event);
LOG_WARNING(Service_BTM, "(STUBBED) called");
rb.PushCopyObjects(connection_event.readable);
}
void GetDiscoveryEvent(Kernel::HLERequestContext& ctx) {
auto& kernel = Core::System::GetInstance().Kernel();
service_discovery =
Kernel::Event::Create(kernel, Kernel::ResetType::OneShot, "IBtmUserCore:Discovery");
LOG_WARNING(Service_BTM, "(STUBBED) called");
IPC::ResponseBuilder rb{ctx, 2, 1};
rb.Push(RESULT_SUCCESS);
rb.PushCopyObjects(service_discovery);
LOG_WARNING(Service_BTM, "(STUBBED) called");
rb.PushCopyObjects(service_discovery.readable);
}
void GetConfigEvent(Kernel::HLERequestContext& ctx) {
auto& kernel = Core::System::GetInstance().Kernel();
config_event =
Kernel::Event::Create(kernel, Kernel::ResetType::OneShot, "IBtmUserCore:ConfigEvent");
LOG_WARNING(Service_BTM, "(STUBBED) called");
IPC::ResponseBuilder rb{ctx, 2, 1};
rb.Push(RESULT_SUCCESS);
rb.PushCopyObjects(config_event);
LOG_WARNING(Service_BTM, "(STUBBED) called");
rb.PushCopyObjects(config_event.readable);
}
Kernel::SharedPtr<Kernel::Event> scan_event;
Kernel::SharedPtr<Kernel::Event> connection_event;
Kernel::SharedPtr<Kernel::Event> service_discovery;
Kernel::SharedPtr<Kernel::Event> config_event;
Kernel::EventPair scan_event;
Kernel::EventPair connection_event;
Kernel::EventPair service_discovery;
Kernel::EventPair config_event;
};
class BTM_USR final : public ServiceFramework<BTM_USR> {
@@ -111,10 +119,11 @@ public:
private:
void GetCoreImpl(Kernel::HLERequestContext& ctx) {
LOG_DEBUG(Service_BTM, "called");
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(RESULT_SUCCESS);
rb.PushIpcInterface<IBtmUserCore>();
LOG_DEBUG(Service_BTM, "called");
}
};
@@ -209,11 +218,11 @@ public:
private:
void GetCoreImpl(Kernel::HLERequestContext& ctx) {
LOG_DEBUG(Service_BTM, "called");
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(RESULT_SUCCESS);
rb.PushIpcInterface<IBtmSystemCore>();
LOG_DEBUG(Service_BTM, "called");
}
};

View File

@@ -17,11 +17,13 @@ public:
static const FunctionInfo functions[] = {
{0, nullptr, "SubmitContext"},
{1, nullptr, "CreateReport"},
{2, nullptr, "Unknown1"},
{3, nullptr, "Unknown2"},
{4, nullptr, "Unknown3"},
{5, nullptr, "Unknown4"},
{6, nullptr, "Unknown5"},
{2, nullptr, "SetInitialLaunchSettingsCompletionTime"},
{3, nullptr, "ClearInitialLaunchSettingsCompletionTime"},
{4, nullptr, "UpdatePowerOnTime"},
{5, nullptr, "UpdateAwakeTime"},
{6, nullptr, "SubmitMultipleCategoryContext"},
{7, nullptr, "UpdateApplicationLaunchTime"},
{8, nullptr, "ClearApplicationLaunchTime"},
};
// clang-format on

View File

@@ -42,11 +42,11 @@ public:
private:
void Initialize(Kernel::HLERequestContext& ctx) {
LOG_DEBUG(Service_FGM, "called");
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(RESULT_SUCCESS);
rb.PushIpcInterface<IRequest>();
LOG_DEBUG(Service_FGM, "called");
}
};

View File

@@ -113,6 +113,18 @@ ResultCode VfsDirectoryServiceWrapper::DeleteDirectoryRecursively(const std::str
return RESULT_SUCCESS;
}
ResultCode VfsDirectoryServiceWrapper::CleanDirectoryRecursively(const std::string& path) const {
const std::string sanitized_path(FileUtil::SanitizePath(path));
auto dir = GetDirectoryRelativeWrapped(backing, FileUtil::GetParentPath(sanitized_path));
if (!dir->CleanSubdirectoryRecursive(FileUtil::GetFilename(sanitized_path))) {
// TODO(DarkLordZach): Find a better error code for this
return ResultCode(-1);
}
return RESULT_SUCCESS;
}
ResultCode VfsDirectoryServiceWrapper::RenameFile(const std::string& src_path_,
const std::string& dest_path_) const {
std::string src_path(FileUtil::SanitizePath(src_path_));
@@ -329,20 +341,9 @@ ResultVal<FileSys::VirtualDir> OpenSDMC() {
return sdmc_factory->Open();
}
std::shared_ptr<FileSys::RegisteredCacheUnion> registered_cache_union;
std::shared_ptr<FileSys::RegisteredCacheUnion> GetUnionContents() {
if (registered_cache_union == nullptr) {
registered_cache_union =
std::make_shared<FileSys::RegisteredCacheUnion>(std::vector<FileSys::RegisteredCache*>{
GetSystemNANDContents(), GetUserNANDContents(), GetSDMCContents()});
}
return registered_cache_union;
}
void ClearUnionContents() {
registered_cache_union = nullptr;
FileSys::RegisteredCacheUnion GetUnionContents() {
return FileSys::RegisteredCacheUnion{
{GetSystemNANDContents(), GetUserNANDContents(), GetSDMCContents()}};
}
FileSys::RegisteredCache* GetSystemNANDContents() {
@@ -395,7 +396,6 @@ void CreateFactories(FileSys::VfsFilesystem& vfs, bool overwrite) {
bis_factory = nullptr;
save_data_factory = nullptr;
sdmc_factory = nullptr;
ClearUnionContents();
}
auto nand_directory = vfs.OpenDirectory(FileUtil::GetUserPath(FileUtil::UserPath::NANDDir),

View File

@@ -48,8 +48,7 @@ ResultVal<FileSys::VirtualDir> OpenSaveData(FileSys::SaveDataSpaceId space,
ResultVal<FileSys::VirtualDir> OpenSaveDataSpace(FileSys::SaveDataSpaceId space);
ResultVal<FileSys::VirtualDir> OpenSDMC();
std::shared_ptr<FileSys::RegisteredCacheUnion> GetUnionContents();
void ClearUnionContents();
FileSys::RegisteredCacheUnion GetUnionContents();
FileSys::RegisteredCache* GetSystemNANDContents();
FileSys::RegisteredCache* GetUserNANDContents();
@@ -113,6 +112,18 @@ public:
*/
ResultCode DeleteDirectoryRecursively(const std::string& path) const;
/**
* Cleans the specified directory. This is similar to DeleteDirectoryRecursively,
* in that it deletes all the contents of the specified directory, however, this
* function does *not* delete the directory itself. It only deletes everything
* within it.
*
* @param path Path relative to the archive.
*
* @return Result of the operation.
*/
ResultCode CleanDirectoryRecursively(const std::string& path) const;
/**
* Rename a File specified by its path
* @param src_path Source path relative to the archive

View File

@@ -62,11 +62,13 @@ private:
// Error checking
if (length < 0) {
LOG_ERROR(Service_FS, "Length is less than 0, length={}", length);
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(FileSys::ERROR_INVALID_SIZE);
return;
}
if (offset < 0) {
LOG_ERROR(Service_FS, "Offset is less than 0, offset={}", offset);
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(FileSys::ERROR_INVALID_OFFSET);
return;
@@ -107,11 +109,13 @@ private:
// Error checking
if (length < 0) {
LOG_ERROR(Service_FS, "Length is less than 0, length={}", length);
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(FileSys::ERROR_INVALID_SIZE);
return;
}
if (offset < 0) {
LOG_ERROR(Service_FS, "Offset is less than 0, offset={}", offset);
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(FileSys::ERROR_INVALID_OFFSET);
return;
@@ -138,11 +142,13 @@ private:
// Error checking
if (length < 0) {
LOG_ERROR(Service_FS, "Length is less than 0, length={}", length);
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(FileSys::ERROR_INVALID_SIZE);
return;
}
if (offset < 0) {
LOG_ERROR(Service_FS, "Offset is less than 0, offset={}", offset);
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(FileSys::ERROR_INVALID_OFFSET);
return;
@@ -180,9 +186,10 @@ private:
void SetSize(Kernel::HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
const u64 size = rp.Pop<u64>();
backend->Resize(size);
LOG_DEBUG(Service_FS, "called, size={}", size);
backend->Resize(size);
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS);
}
@@ -284,7 +291,7 @@ public:
{10, &IFileSystem::Commit, "Commit"},
{11, nullptr, "GetFreeSpaceSize"},
{12, nullptr, "GetTotalSpaceSize"},
{13, nullptr, "CleanDirectoryRecursively"},
{13, &IFileSystem::CleanDirectoryRecursively, "CleanDirectoryRecursively"},
{14, nullptr, "GetFileTimeStampRaw"},
{15, nullptr, "QueryEntry"},
};
@@ -354,6 +361,16 @@ public:
rb.Push(backend.DeleteDirectoryRecursively(name));
}
void CleanDirectoryRecursively(Kernel::HLERequestContext& ctx) {
const auto file_buffer = ctx.ReadBuffer();
const std::string name = Common::StringFromBuffer(file_buffer);
LOG_DEBUG(Service_FS, "called. Directory: {}", name);
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(backend.CleanDirectoryRecursively(name));
}
void RenameFile(Kernel::HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
@@ -465,6 +482,8 @@ public:
}
void ReadSaveDataInfo(Kernel::HLERequestContext& ctx) {
LOG_DEBUG(Service_FS, "called");
// Calculate how many entries we can fit in the output buffer
const u64 count_entries = ctx.GetWriteBufferSize() / sizeof(SaveDataInfo);
@@ -703,6 +722,8 @@ void FSP_SRV::OpenFileSystemWithPatch(Kernel::HLERequestContext& ctx) {
const auto type = rp.PopRaw<FileSystemType>();
const auto title_id = rp.PopRaw<u64>();
LOG_WARNING(Service_FS, "(STUBBED) called with type={}, title_id={:016X}",
static_cast<u8>(type), title_id);
IPC::ResponseBuilder rb{ctx, 2, 0, 0};
rb.Push(ResultCode(-1));
@@ -738,6 +759,7 @@ void FSP_SRV::MountSaveData(Kernel::HLERequestContext& ctx) {
auto space_id = rp.PopRaw<FileSys::SaveDataSpaceId>();
auto unk = rp.Pop<u32>();
LOG_INFO(Service_FS, "called with unknown={:08X}", unk);
auto save_struct = rp.PopRaw<FileSys::SaveDataDescriptor>();
auto dir = OpenSaveData(space_id, save_struct);
@@ -763,6 +785,7 @@ void FSP_SRV::OpenReadOnlySaveDataFileSystem(Kernel::HLERequestContext& ctx) {
void FSP_SRV::OpenSaveDataInfoReaderBySaveDataSpaceId(Kernel::HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
const auto space = rp.PopRaw<FileSys::SaveDataSpaceId>();
LOG_INFO(Service_FS, "called, space={}", static_cast<u8>(space));
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(RESULT_SUCCESS);

View File

@@ -12,7 +12,9 @@
#include "core/core.h"
#include "core/core_timing.h"
#include "core/frontend/input.h"
#include "core/hle/kernel/event.h"
#include "core/hle/kernel/kernel.h"
#include "core/hle/kernel/readable_event.h"
#include "core/hle/kernel/writable_event.h"
#include "core/hle/service/hid/controllers/npad.h"
#include "core/settings.h"
@@ -167,8 +169,8 @@ void Controller_NPad::InitNewlyAddedControler(std::size_t controller_idx) {
void Controller_NPad::OnInit() {
auto& kernel = Core::System::GetInstance().Kernel();
styleset_changed_event =
Kernel::Event::Create(kernel, Kernel::ResetType::OneShot, "npad:NpadStyleSetChanged");
styleset_changed_event = Kernel::WritableEvent::CreateEventPair(
kernel, Kernel::ResetType::OneShot, "npad:NpadStyleSetChanged");
if (!IsControllerActivated()) {
return;
@@ -494,7 +496,7 @@ void Controller_NPad::SetSupportedNPadIdTypes(u8* data, std::size_t length) {
had_controller_update = true;
}
if (had_controller_update) {
styleset_changed_event->Signal();
styleset_changed_event.writable->Signal();
}
}
}
@@ -509,7 +511,7 @@ std::size_t Controller_NPad::GetSupportedNPadIdTypesSize() const {
}
void Controller_NPad::SetHoldType(NpadHoldType joy_hold_type) {
styleset_changed_event->Signal();
styleset_changed_event.writable->Signal();
hold_type = joy_hold_type;
}
@@ -518,12 +520,15 @@ Controller_NPad::NpadHoldType Controller_NPad::GetHoldType() const {
}
void Controller_NPad::SetNpadMode(u32 npad_id, NPadAssignments assignment_mode) {
ASSERT(npad_id < shared_memory_entries.size());
shared_memory_entries[npad_id].pad_assignment = assignment_mode;
const std::size_t npad_index = NPadIdToIndex(npad_id);
ASSERT(npad_index < shared_memory_entries.size());
shared_memory_entries[npad_index].pad_assignment = assignment_mode;
}
void Controller_NPad::VibrateController(const std::vector<u32>& controller_ids,
const std::vector<Vibration>& vibrations) {
LOG_WARNING(Service_HID, "(STUBBED) called");
if (!can_controllers_vibrate) {
return;
}
@@ -533,15 +538,14 @@ void Controller_NPad::VibrateController(const std::vector<u32>& controller_ids,
// TODO(ogniK): Vibrate the physical controller
}
}
LOG_WARNING(Service_HID, "(STUBBED) called");
last_processed_vibration = vibrations.back();
}
Kernel::SharedPtr<Kernel::Event> Controller_NPad::GetStyleSetChangedEvent() const {
Kernel::SharedPtr<Kernel::ReadableEvent> Controller_NPad::GetStyleSetChangedEvent() const {
// TODO(ogniK): Figure out the best time to signal this event. This event seems that it should
// be signalled at least once, and signaled after a new controller is connected?
styleset_changed_event->Signal();
return styleset_changed_event;
styleset_changed_event.writable->Signal();
return styleset_changed_event.readable;
}
Controller_NPad::Vibration Controller_NPad::GetLastVibration() const {
@@ -575,8 +579,8 @@ void Controller_NPad::AddNewControllerAt(NPadControllerType controller, u32 npad
return;
}
connected_controllers[npad_id] = {controller, true};
InitNewlyAddedControler(npad_id);
connected_controllers[NPadIdToIndex(npad_id)] = {controller, true};
InitNewlyAddedControler(NPadIdToIndex(npad_id));
}
void Controller_NPad::ConnectNPad(u32 npad_id) {

View File

@@ -8,7 +8,8 @@
#include "common/bit_field.h"
#include "common/common_types.h"
#include "core/frontend/input.h"
#include "core/hle/kernel/event.h"
#include "core/hle/kernel/object.h"
#include "core/hle/kernel/writable_event.h"
#include "core/hle/service/hid/controllers/controller_base.h"
#include "core/settings.h"
@@ -80,9 +81,9 @@ public:
struct LedPattern {
explicit LedPattern(u64 light1, u64 light2, u64 light3, u64 light4) {
position1.Assign(light1);
position1.Assign(light2);
position1.Assign(light3);
position1.Assign(light4);
position2.Assign(light2);
position3.Assign(light3);
position4.Assign(light4);
}
union {
u64 raw{};
@@ -108,7 +109,7 @@ public:
void VibrateController(const std::vector<u32>& controller_ids,
const std::vector<Vibration>& vibrations);
Kernel::SharedPtr<Kernel::Event> GetStyleSetChangedEvent() const;
Kernel::SharedPtr<Kernel::ReadableEvent> GetStyleSetChangedEvent() const;
Vibration GetLastVibration() const;
void AddNewController(NPadControllerType controller);
@@ -303,7 +304,7 @@ private:
sticks;
std::vector<u32> supported_npad_id_types{};
NpadHoldType hold_type{NpadHoldType::Vertical};
Kernel::SharedPtr<Kernel::Event> styleset_changed_event;
Kernel::EventPair styleset_changed_event;
Vibration last_processed_vibration{};
std::array<ControllerHolder, 10> connected_controllers{};
bool can_controllers_vibrate{true};

View File

@@ -13,8 +13,9 @@
#include "core/hle/ipc_helpers.h"
#include "core/hle/kernel/client_port.h"
#include "core/hle/kernel/client_session.h"
#include "core/hle/kernel/event.h"
#include "core/hle/kernel/readable_event.h"
#include "core/hle/kernel/shared_memory.h"
#include "core/hle/kernel/writable_event.h"
#include "core/hle/service/hid/hid.h"
#include "core/hle/service/hid/irs.h"
#include "core/hle/service/hid/xcd.h"
@@ -124,10 +125,11 @@ public:
private:
void GetSharedMemoryHandle(Kernel::HLERequestContext& ctx) {
LOG_DEBUG(Service_HID, "called");
IPC::ResponseBuilder rb{ctx, 2, 1};
rb.Push(RESULT_SUCCESS);
rb.PushCopyObjects(shared_mem);
LOG_DEBUG(Service_HID, "called");
}
void UpdateControllers(u64 userdata, int cycles_late) {
@@ -163,9 +165,10 @@ public:
private:
void ActivateVibrationDevice(Kernel::HLERequestContext& ctx) {
LOG_WARNING(Service_HID, "(STUBBED) called");
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS);
LOG_WARNING(Service_HID, "(STUBBED) called");
}
};
@@ -303,6 +306,8 @@ private:
std::shared_ptr<IAppletResource> applet_resource;
void CreateAppletResource(Kernel::HLERequestContext& ctx) {
LOG_DEBUG(Service_HID, "called");
if (applet_resource == nullptr) {
applet_resource = std::make_shared<IAppletResource>();
}
@@ -310,206 +315,228 @@ private:
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(RESULT_SUCCESS);
rb.PushIpcInterface<IAppletResource>(applet_resource);
LOG_DEBUG(Service_HID, "called");
}
void ActivateXpad(Kernel::HLERequestContext& ctx) {
LOG_DEBUG(Service_HID, "called");
applet_resource->ActivateController(HidController::XPad);
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS);
LOG_DEBUG(Service_HID, "called");
}
void ActivateDebugPad(Kernel::HLERequestContext& ctx) {
LOG_DEBUG(Service_HID, "called");
applet_resource->ActivateController(HidController::DebugPad);
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS);
LOG_DEBUG(Service_HID, "called");
}
void ActivateTouchScreen(Kernel::HLERequestContext& ctx) {
LOG_DEBUG(Service_HID, "called");
applet_resource->ActivateController(HidController::Touchscreen);
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS);
LOG_DEBUG(Service_HID, "called");
}
void ActivateMouse(Kernel::HLERequestContext& ctx) {
LOG_DEBUG(Service_HID, "called");
applet_resource->ActivateController(HidController::Mouse);
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS);
LOG_DEBUG(Service_HID, "called");
}
void ActivateKeyboard(Kernel::HLERequestContext& ctx) {
LOG_DEBUG(Service_HID, "called");
applet_resource->ActivateController(HidController::Keyboard);
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS);
LOG_DEBUG(Service_HID, "called");
}
void ActivateGesture(Kernel::HLERequestContext& ctx) {
LOG_DEBUG(Service_HID, "called");
applet_resource->ActivateController(HidController::Gesture);
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS);
LOG_DEBUG(Service_HID, "called");
}
void ActivateNpadWithRevision(Kernel::HLERequestContext& ctx) {
// Should have no effect with how our npad sets up the data
LOG_DEBUG(Service_HID, "called");
applet_resource->ActivateController(HidController::NPad);
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS);
LOG_DEBUG(Service_HID, "called");
}
void StartSixAxisSensor(Kernel::HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
auto handle = rp.PopRaw<u32>();
LOG_WARNING(Service_HID, "(STUBBED) called with handle={}", handle);
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS);
LOG_WARNING(Service_HID, "(STUBBED) called");
}
void SetGyroscopeZeroDriftMode(Kernel::HLERequestContext& ctx) {
LOG_WARNING(Service_HID, "(STUBBED) called");
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS);
LOG_WARNING(Service_HID, "(STUBBED) called");
}
void IsSixAxisSensorAtRest(Kernel::HLERequestContext& ctx) {
LOG_WARNING(Service_HID, "(STUBBED) called");
IPC::ResponseBuilder rb{ctx, 3};
rb.Push(RESULT_SUCCESS);
// TODO (Hexagon12): Properly implement reading gyroscope values from controllers.
rb.Push(true);
LOG_WARNING(Service_HID, "(STUBBED) called");
}
void SetSupportedNpadStyleSet(Kernel::HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
auto supported_styleset = rp.PopRaw<u32>();
LOG_DEBUG(Service_HID, "called with supported_styleset={}", supported_styleset);
applet_resource->GetController<Controller_NPad>(HidController::NPad)
.SetSupportedStyleSet({supported_styleset});
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS);
LOG_DEBUG(Service_HID, "called");
}
void GetSupportedNpadStyleSet(Kernel::HLERequestContext& ctx) {
LOG_DEBUG(Service_HID, "called");
auto& controller = applet_resource->GetController<Controller_NPad>(HidController::NPad);
IPC::ResponseBuilder rb{ctx, 3};
rb.Push(RESULT_SUCCESS);
rb.Push<u32>(controller.GetSupportedStyleSet().raw);
LOG_DEBUG(Service_HID, "called");
}
void SetSupportedNpadIdType(Kernel::HLERequestContext& ctx) {
LOG_DEBUG(Service_HID, "called");
applet_resource->GetController<Controller_NPad>(HidController::NPad)
.SetSupportedNPadIdTypes(ctx.ReadBuffer().data(), ctx.GetReadBufferSize());
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS);
LOG_DEBUG(Service_HID, "called");
}
void ActivateNpad(Kernel::HLERequestContext& ctx) {
LOG_DEBUG(Service_HID, "called");
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS);
applet_resource->ActivateController(HidController::NPad);
LOG_DEBUG(Service_HID, "called");
}
void AcquireNpadStyleSetUpdateEventHandle(Kernel::HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
auto npad_id = rp.PopRaw<u32>();
LOG_DEBUG(Service_HID, "called with npad_id={}", npad_id);
IPC::ResponseBuilder rb{ctx, 2, 1};
rb.Push(RESULT_SUCCESS);
rb.PushCopyObjects(applet_resource->GetController<Controller_NPad>(HidController::NPad)
.GetStyleSetChangedEvent());
LOG_DEBUG(Service_HID, "called");
}
void DisconnectNpad(Kernel::HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
auto npad_id = rp.PopRaw<u32>();
LOG_DEBUG(Service_HID, "called with npad_id={}", npad_id);
applet_resource->GetController<Controller_NPad>(HidController::NPad)
.DisconnectNPad(npad_id);
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS);
LOG_DEBUG(Service_HID, "called");
}
void GetPlayerLedPattern(Kernel::HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
auto npad_id = rp.PopRaw<u32>();
LOG_DEBUG(Service_HID, "called with npad_id={}", npad_id);
IPC::ResponseBuilder rb{ctx, 4};
rb.Push(RESULT_SUCCESS);
rb.PushRaw<u64>(applet_resource->GetController<Controller_NPad>(HidController::NPad)
.GetLedPattern(npad_id)
.raw);
LOG_DEBUG(Service_HID, "called");
}
void SetNpadJoyHoldType(Kernel::HLERequestContext& ctx) {
auto& controller = applet_resource->GetController<Controller_NPad>(HidController::NPad);
IPC::RequestParser rp{ctx};
const auto hold_type = rp.PopRaw<u64>();
LOG_DEBUG(Service_HID, "called with hold_type={}", hold_type);
auto& controller = applet_resource->GetController<Controller_NPad>(HidController::NPad);
controller.SetHoldType(Controller_NPad::NpadHoldType{hold_type});
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS);
LOG_DEBUG(Service_HID, "called");
}
void GetNpadJoyHoldType(Kernel::HLERequestContext& ctx) {
LOG_DEBUG(Service_HID, "called");
const auto& controller =
applet_resource->GetController<Controller_NPad>(HidController::NPad);
IPC::ResponseBuilder rb{ctx, 4};
rb.Push(RESULT_SUCCESS);
rb.Push<u64>(static_cast<u64>(controller.GetHoldType()));
LOG_DEBUG(Service_HID, "called");
}
void SetNpadJoyAssignmentModeSingleByDefault(Kernel::HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
auto npad_id = rp.PopRaw<u32>();
LOG_WARNING(Service_HID, "(STUBBED) called with npad_id={}", npad_id);
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS);
LOG_WARNING(Service_HID, "(STUBBED) called");
}
void BeginPermitVibrationSession(Kernel::HLERequestContext& ctx) {
LOG_DEBUG(Service_HID, "called");
applet_resource->GetController<Controller_NPad>(HidController::NPad)
.SetVibrationEnabled(true);
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS);
LOG_DEBUG(Service_HID, "called");
}
void EndPermitVibrationSession(Kernel::HLERequestContext& ctx) {
LOG_DEBUG(Service_HID, "called");
applet_resource->GetController<Controller_NPad>(HidController::NPad)
.SetVibrationEnabled(false);
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS);
LOG_DEBUG(Service_HID, "called");
}
void SendVibrationValue(Kernel::HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
const auto controller_id = rp.PopRaw<u32>();
const auto vibration_values = rp.PopRaw<Controller_NPad::Vibration>();
LOG_DEBUG(Service_HID, "called with controller_id={}", controller_id);
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS);
applet_resource->GetController<Controller_NPad>(HidController::NPad)
.VibrateController({controller_id}, {vibration_values});
LOG_DEBUG(Service_HID, "called");
}
void SendVibrationValues(Kernel::HLERequestContext& ctx) {
LOG_DEBUG(Service_HID, "called");
const auto controllers = ctx.ReadBuffer(0);
const auto vibrations = ctx.ReadBuffer(1);
@@ -527,86 +554,96 @@ private:
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS);
LOG_DEBUG(Service_HID, "called");
}
void GetActualVibrationValue(Kernel::HLERequestContext& ctx) {
LOG_DEBUG(Service_HID, "called");
IPC::ResponseBuilder rb{ctx, 6};
rb.Push(RESULT_SUCCESS);
rb.PushRaw<Controller_NPad::Vibration>(
applet_resource->GetController<Controller_NPad>(HidController::NPad)
.GetLastVibration());
LOG_DEBUG(Service_HID, "called");
}
void SetNpadJoyAssignmentModeDual(Kernel::HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
const auto npad_id = rp.PopRaw<u32>();
LOG_DEBUG(Service_HID, "called with npad_id={}", npad_id);
auto& controller = applet_resource->GetController<Controller_NPad>(HidController::NPad);
controller.SetNpadMode(npad_id, Controller_NPad::NPadAssignments::Dual);
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS);
LOG_DEBUG(Service_HID, "called");
}
void MergeSingleJoyAsDualJoy(Kernel::HLERequestContext& ctx) {
LOG_WARNING(Service_HID, "(STUBBED) called");
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS);
LOG_WARNING(Service_HID, "(STUBBED) called");
}
void SetNpadHandheldActivationMode(Kernel::HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
auto mode = rp.PopRaw<u32>();
LOG_WARNING(Service_HID, "(STUBBED) called with mode={}", mode);
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS);
LOG_WARNING(Service_HID, "(STUBBED) called");
}
void GetVibrationDeviceInfo(Kernel::HLERequestContext& ctx) {
LOG_DEBUG(Service_HID, "called");
IPC::ResponseBuilder rb{ctx, 4};
rb.Push(RESULT_SUCCESS);
rb.Push<u32>(1);
rb.Push<u32>(0);
LOG_DEBUG(Service_HID, "called");
}
void CreateActiveVibrationDeviceList(Kernel::HLERequestContext& ctx) {
LOG_DEBUG(Service_HID, "called");
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(RESULT_SUCCESS);
rb.PushIpcInterface<IActiveVibrationDeviceList>();
LOG_DEBUG(Service_HID, "called");
}
void ActivateConsoleSixAxisSensor(Kernel::HLERequestContext& ctx) {
LOG_WARNING(Service_HID, "(STUBBED) called");
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS);
LOG_WARNING(Service_HID, "(STUBBED) called");
}
void StartConsoleSixAxisSensor(Kernel::HLERequestContext& ctx) {
LOG_WARNING(Service_HID, "(STUBBED) called");
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS);
LOG_WARNING(Service_HID, "(STUBBED) called");
}
void StopSixAxisSensor(Kernel::HLERequestContext& ctx) {
LOG_WARNING(Service_HID, "(STUBBED) called");
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS);
LOG_WARNING(Service_HID, "(STUBBED) called");
}
void SetIsPalmaAllConnectable(Kernel::HLERequestContext& ctx) {
LOG_WARNING(Service_HID, "(STUBBED) called");
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS);
LOG_WARNING(Service_HID, "(STUBBED) called");
}
void SetPalmaBoostMode(Kernel::HLERequestContext& ctx) {
LOG_WARNING(Service_HID, "(STUBBED) called");
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS);
LOG_WARNING(Service_HID, "(STUBBED) called");
}
};

View File

@@ -44,115 +44,133 @@ IRS::IRS() : ServiceFramework{"irs"} {
}
void IRS::ActivateIrsensor(Kernel::HLERequestContext& ctx) {
LOG_WARNING(Service_IRS, "(STUBBED) called");
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS);
LOG_WARNING(Service_IRS, "(STUBBED) called");
}
void IRS::DeactivateIrsensor(Kernel::HLERequestContext& ctx) {
LOG_WARNING(Service_IRS, "(STUBBED) called");
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS);
LOG_WARNING(Service_IRS, "(STUBBED) called");
}
void IRS::GetIrsensorSharedMemoryHandle(Kernel::HLERequestContext& ctx) {
LOG_DEBUG(Service_IRS, "called");
IPC::ResponseBuilder rb{ctx, 2, 1};
rb.Push(RESULT_SUCCESS);
rb.PushCopyObjects(shared_mem);
LOG_DEBUG(Service_IRS, "called");
}
void IRS::StopImageProcessor(Kernel::HLERequestContext& ctx) {
LOG_WARNING(Service_IRS, "(STUBBED) called");
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS);
LOG_WARNING(Service_IRS, "(STUBBED) called");
}
void IRS::RunMomentProcessor(Kernel::HLERequestContext& ctx) {
LOG_WARNING(Service_IRS, "(STUBBED) called");
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS);
LOG_WARNING(Service_IRS, "(STUBBED) called");
}
void IRS::RunClusteringProcessor(Kernel::HLERequestContext& ctx) {
LOG_WARNING(Service_IRS, "(STUBBED) called");
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS);
LOG_WARNING(Service_IRS, "(STUBBED) called");
}
void IRS::RunImageTransferProcessor(Kernel::HLERequestContext& ctx) {
LOG_WARNING(Service_IRS, "(STUBBED) called");
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS);
LOG_WARNING(Service_IRS, "(STUBBED) called");
}
void IRS::GetImageTransferProcessorState(Kernel::HLERequestContext& ctx) {
LOG_WARNING(Service_IRS, "(STUBBED) called");
IPC::ResponseBuilder rb{ctx, 5};
rb.Push(RESULT_SUCCESS);
rb.PushRaw<u64>(CoreTiming::GetTicks());
rb.PushRaw<u32>(0);
LOG_WARNING(Service_IRS, "(STUBBED) called");
}
void IRS::RunTeraPluginProcessor(Kernel::HLERequestContext& ctx) {
LOG_WARNING(Service_IRS, "(STUBBED) called");
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS);
LOG_WARNING(Service_IRS, "(STUBBED) called");
}
void IRS::GetNpadIrCameraHandle(Kernel::HLERequestContext& ctx) {
LOG_WARNING(Service_IRS, "(STUBBED) called");
IPC::ResponseBuilder rb{ctx, 3};
rb.Push(RESULT_SUCCESS);
rb.PushRaw<u32>(device_handle);
LOG_WARNING(Service_IRS, "(STUBBED) called");
}
void IRS::RunPointingProcessor(Kernel::HLERequestContext& ctx) {
LOG_WARNING(Service_IRS, "(STUBBED) called");
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS);
LOG_WARNING(Service_IRS, "(STUBBED) called");
}
void IRS::SuspendImageProcessor(Kernel::HLERequestContext& ctx) {
LOG_WARNING(Service_IRS, "(STUBBED) called");
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS);
LOG_WARNING(Service_IRS, "(STUBBED) called");
}
void IRS::CheckFirmwareVersion(Kernel::HLERequestContext& ctx) {
LOG_WARNING(Service_IRS, "(STUBBED) called");
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS);
LOG_WARNING(Service_IRS, "(STUBBED) called");
}
void IRS::SetFunctionLevel(Kernel::HLERequestContext& ctx) {
LOG_WARNING(Service_IRS, "(STUBBED) called");
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS);
LOG_WARNING(Service_IRS, "(STUBBED) called");
}
void IRS::RunImageTransferExProcessor(Kernel::HLERequestContext& ctx) {
LOG_WARNING(Service_IRS, "(STUBBED) called");
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS);
LOG_WARNING(Service_IRS, "(STUBBED) called");
}
void IRS::RunIrLedProcessor(Kernel::HLERequestContext& ctx) {
LOG_WARNING(Service_IRS, "(STUBBED) called");
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS);
LOG_WARNING(Service_IRS, "(STUBBED) called");
}
void IRS::StopImageProcessorAsync(Kernel::HLERequestContext& ctx) {
LOG_WARNING(Service_IRS, "(STUBBED) called");
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS);
LOG_WARNING(Service_IRS, "(STUBBED) called");
}
void IRS::ActivateIrsensorWithFunctionLevel(Kernel::HLERequestContext& ctx) {
LOG_WARNING(Service_IRS, "(STUBBED) called");
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS);
LOG_WARNING(Service_IRS, "(STUBBED) called");
}
IRS::~IRS() = default;

View File

@@ -55,29 +55,29 @@ public:
private:
void EnableVrMode(Kernel::HLERequestContext& ctx) {
LOG_DEBUG(Service_LBL, "called");
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS);
vr_mode_enabled = true;
LOG_DEBUG(Service_LBL, "called");
}
void DisableVrMode(Kernel::HLERequestContext& ctx) {
LOG_DEBUG(Service_LBL, "called");
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS);
vr_mode_enabled = false;
LOG_DEBUG(Service_LBL, "called");
}
void IsVrModeEnabled(Kernel::HLERequestContext& ctx) {
LOG_DEBUG(Service_LBL, "called");
IPC::ResponseBuilder rb{ctx, 3};
rb.Push(RESULT_SUCCESS);
rb.Push(vr_mode_enabled);
LOG_DEBUG(Service_LBL, "called");
}
bool vr_mode_enabled = false;

View File

@@ -44,11 +44,11 @@ public:
}
void CreateMonitorService(Kernel::HLERequestContext& ctx) {
LOG_DEBUG(Service_LDN, "called");
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(RESULT_SUCCESS);
rb.PushIpcInterface<IMonitorService>();
LOG_DEBUG(Service_LDN, "called");
}
};
@@ -104,11 +104,11 @@ public:
}
void CreateSystemLocalCommunicationService(Kernel::HLERequestContext& ctx) {
LOG_DEBUG(Service_LDN, "called");
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(RESULT_SUCCESS);
rb.PushIpcInterface<ILocalCommunicationService>("ISystemLocalCommunicationService");
LOG_DEBUG(Service_LDN, "called");
}
};
@@ -125,11 +125,11 @@ public:
}
void CreateUserLocalCommunicationService(Kernel::HLERequestContext& ctx) {
LOG_DEBUG(Service_LDN, "called");
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(RESULT_SUCCESS);
rb.PushIpcInterface<ILocalCommunicationService>("IUserLocalCommunicationService");
LOG_DEBUG(Service_LDN, "called");
}
};

View File

@@ -97,6 +97,8 @@ public:
rp.Skip(2, false);
const VAddr nrr_addr{rp.Pop<VAddr>()};
const u64 nrr_size{rp.Pop<u64>()};
LOG_DEBUG(Service_LDR, "called with nrr_addr={:016X}, nrr_size={:016X}", nrr_addr,
nrr_size);
if (!initialized) {
LOG_ERROR(Service_LDR, "LDR:RO not initialized before use!");
@@ -189,6 +191,7 @@ public:
IPC::RequestParser rp{ctx};
rp.Skip(2, false);
const auto nrr_addr{rp.Pop<VAddr>()};
LOG_DEBUG(Service_LDR, "called with nrr_addr={:016X}", nrr_addr);
if (!Common::Is4KBAligned(nrr_addr)) {
LOG_ERROR(Service_LDR, "NRR Address has invalid alignment (actual {:016X})!", nrr_addr);
@@ -219,6 +222,10 @@ public:
const u64 nro_size{rp.Pop<u64>()};
const VAddr bss_addr{rp.Pop<VAddr>()};
const u64 bss_size{rp.Pop<u64>()};
LOG_DEBUG(
Service_LDR,
"called with nro_addr={:016X}, nro_size={:016X}, bss_addr={:016X}, bss_size={:016X}",
nro_addr, nro_size, bss_addr, bss_size);
if (!initialized) {
LOG_ERROR(Service_LDR, "LDR:RO not initialized before use!");
@@ -345,6 +352,8 @@ public:
rp.Skip(2, false);
const VAddr mapped_addr{rp.PopRaw<VAddr>()};
const VAddr heap_addr{rp.PopRaw<VAddr>()};
LOG_DEBUG(Service_LDR, "called with mapped_addr={:016X}, heap_addr={:016X}", mapped_addr,
heap_addr);
if (!initialized) {
LOG_ERROR(Service_LDR, "LDR:RO not initialized before use!");
@@ -393,11 +402,12 @@ public:
}
void Initialize(Kernel::HLERequestContext& ctx) {
LOG_WARNING(Service_LDR, "(STUBBED) called");
initialized = true;
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS);
LOG_WARNING(Service_LDR, "(STUBBED) called");
}
private:

View File

@@ -209,11 +209,11 @@ public:
* 0: ResultCode
*/
void OpenLogger(Kernel::HLERequestContext& ctx) {
LOG_DEBUG(Service_LM, "called");
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(RESULT_SUCCESS);
rb.PushIpcInterface<ILogger>();
LOG_DEBUG(Service_LM, "called");
}
};

View File

@@ -31,12 +31,14 @@ public:
private:
void Initialize(Kernel::HLERequestContext& ctx) {
LOG_WARNING(Service_MM, "(STUBBED) called");
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS);
}
void Finalize(Kernel::HLERequestContext& ctx) {
LOG_WARNING(Service_MM, "(STUBBED) called");
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS);
}
@@ -45,15 +47,16 @@ private:
IPC::RequestParser rp{ctx};
min = rp.Pop<u32>();
max = rp.Pop<u32>();
current = min;
LOG_WARNING(Service_MM, "(STUBBED) called, min=0x{:X}, max=0x{:X}", min, max);
current = min;
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS);
}
void Get(Kernel::HLERequestContext& ctx) {
LOG_WARNING(Service_MM, "(STUBBED) called");
IPC::ResponseBuilder rb{ctx, 3};
rb.Push(RESULT_SUCCESS);
rb.Push(current);
@@ -61,6 +64,7 @@ private:
void InitializeWithId(Kernel::HLERequestContext& ctx) {
LOG_WARNING(Service_MM, "(STUBBED) called");
IPC::ResponseBuilder rb{ctx, 3};
rb.Push(RESULT_SUCCESS);
rb.Push<u32>(id); // Any non zero value
@@ -68,6 +72,7 @@ private:
void FinalizeWithId(Kernel::HLERequestContext& ctx) {
LOG_WARNING(Service_MM, "(STUBBED) called");
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS);
}
@@ -77,16 +82,17 @@ private:
u32 input_id = rp.Pop<u32>();
min = rp.Pop<u32>();
max = rp.Pop<u32>();
current = min;
LOG_WARNING(Service_MM, "(STUBBED) called, input_id=0x{:X}, min=0x{:X}, max=0x{:X}",
input_id, min, max);
current = min;
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS);
}
void GetWithId(Kernel::HLERequestContext& ctx) {
LOG_WARNING(Service_MM, "(STUBBED) called");
IPC::ResponseBuilder rb{ctx, 3};
rb.Push(RESULT_SUCCESS);
rb.Push(current);

View File

@@ -43,11 +43,11 @@ public:
private:
void CreateAmInterface(Kernel::HLERequestContext& ctx) {
LOG_DEBUG(Service_NFC, "called");
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(RESULT_SUCCESS);
rb.PushIpcInterface<IAm>();
LOG_DEBUG(Service_NFC, "called");
}
};
@@ -91,11 +91,11 @@ public:
private:
void CreateUserInterface(Kernel::HLERequestContext& ctx) {
LOG_DEBUG(Service_NFC, "called");
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(RESULT_SUCCESS);
rb.PushIpcInterface<MFIUser>();
LOG_DEBUG(Service_NFC, "called");
}
};
@@ -138,19 +138,19 @@ private:
};
void InitializeOld(Kernel::HLERequestContext& ctx) {
LOG_DEBUG(Service_NFC, "called");
IPC::ResponseBuilder rb{ctx, 2, 0};
rb.Push(RESULT_SUCCESS);
// We don't deal with hardware initialization so we can just stub this.
LOG_DEBUG(Service_NFC, "called");
}
void IsNfcEnabledOld(Kernel::HLERequestContext& ctx) {
LOG_DEBUG(Service_NFC, "IsNfcEnabledOld");
IPC::ResponseBuilder rb{ctx, 3};
rb.Push(RESULT_SUCCESS);
rb.PushRaw<u8>(Settings::values.enable_nfc);
LOG_DEBUG(Service_NFC, "IsNfcEnabledOld");
}
void GetStateOld(Kernel::HLERequestContext& ctx) {
@@ -183,11 +183,11 @@ public:
private:
void CreateUserInterface(Kernel::HLERequestContext& ctx) {
LOG_DEBUG(Service_NFC, "called");
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(RESULT_SUCCESS);
rb.PushIpcInterface<IUser>();
LOG_DEBUG(Service_NFC, "called");
}
};
@@ -241,11 +241,11 @@ public:
private:
void CreateSystemInterface(Kernel::HLERequestContext& ctx) {
LOG_DEBUG(Service_NFC, "called");
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(RESULT_SUCCESS);
rb.PushIpcInterface<ISystem>();
LOG_DEBUG(Service_NFC, "called");
}
};

View File

@@ -7,7 +7,9 @@
#include "common/logging/log.h"
#include "core/core.h"
#include "core/hle/ipc_helpers.h"
#include "core/hle/kernel/event.h"
#include "core/hle/kernel/kernel.h"
#include "core/hle/kernel/readable_event.h"
#include "core/hle/kernel/writable_event.h"
#include "core/hle/lock.h"
#include "core/hle/service/hid/hid.h"
#include "core/hle/service/nfp/nfp.h"
@@ -23,8 +25,8 @@ constexpr ResultCode ERR_TAG_FAILED(ErrorModule::NFP,
Module::Interface::Interface(std::shared_ptr<Module> module, const char* name)
: ServiceFramework(name), module(std::move(module)) {
auto& kernel = Core::System::GetInstance().Kernel();
nfc_tag_load =
Kernel::Event::Create(kernel, Kernel::ResetType::OneShot, "IUser:NFCTagDetected");
nfc_tag_load = Kernel::WritableEvent::CreateEventPair(kernel, Kernel::ResetType::OneShot,
"IUser:NFCTagDetected");
}
Module::Interface::~Interface() = default;
@@ -63,10 +65,10 @@ public:
RegisterHandlers(functions);
auto& kernel = Core::System::GetInstance().Kernel();
deactivate_event =
Kernel::Event::Create(kernel, Kernel::ResetType::OneShot, "IUser:DeactivateEvent");
availability_change_event = Kernel::Event::Create(kernel, Kernel::ResetType::OneShot,
"IUser:AvailabilityChangeEvent");
deactivate_event = Kernel::WritableEvent::CreateEventPair(
kernel, Kernel::ResetType::OneShot, "IUser:DeactivateEvent");
availability_change_event = Kernel::WritableEvent::CreateEventPair(
kernel, Kernel::ResetType::OneShot, "IUser:AvailabilityChangeEvent");
}
private:
@@ -108,30 +110,29 @@ private:
static_assert(sizeof(CommonInfo) == 0x40, "CommonInfo is an invalid size");
void Initialize(Kernel::HLERequestContext& ctx) {
LOG_DEBUG(Service_NFC, "called");
IPC::ResponseBuilder rb{ctx, 2, 0};
rb.Push(RESULT_SUCCESS);
state = State::Initialized;
LOG_DEBUG(Service_NFC, "called");
}
void GetState(Kernel::HLERequestContext& ctx) {
LOG_DEBUG(Service_NFC, "called");
IPC::ResponseBuilder rb{ctx, 3, 0};
rb.Push(RESULT_SUCCESS);
rb.PushRaw<u32>(static_cast<u32>(state));
LOG_DEBUG(Service_NFC, "called");
}
void ListDevices(Kernel::HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
const u32 array_size = rp.Pop<u32>();
LOG_DEBUG(Service_NFP, "called, array_size={}", array_size);
ctx.WriteBuffer(&device_handle, sizeof(device_handle));
LOG_DEBUG(Service_NFP, "called, array_size={}", array_size);
IPC::ResponseBuilder rb{ctx, 3};
rb.Push(RESULT_SUCCESS);
rb.Push<u32>(1);
@@ -141,6 +142,7 @@ private:
IPC::RequestParser rp{ctx};
const u64 dev_handle = rp.Pop<u64>();
LOG_DEBUG(Service_NFP, "called, dev_handle=0x{:X}", dev_handle);
IPC::ResponseBuilder rb{ctx, 3};
rb.Push(RESULT_SUCCESS);
rb.Push<u32>(npad_id);
@@ -150,6 +152,7 @@ private:
IPC::RequestParser rp{ctx};
const u64 dev_handle = rp.Pop<u64>();
LOG_DEBUG(Service_NFP, "called, dev_handle=0x{:X}", dev_handle);
IPC::ResponseBuilder rb{ctx, 2, 1};
rb.Push(RESULT_SUCCESS);
rb.PushCopyObjects(nfp_interface.GetNFCEvent());
@@ -163,15 +166,16 @@ private:
IPC::ResponseBuilder rb{ctx, 2, 1};
rb.Push(RESULT_SUCCESS);
rb.PushCopyObjects(deactivate_event);
rb.PushCopyObjects(deactivate_event.readable);
}
void StopDetection(Kernel::HLERequestContext& ctx) {
LOG_DEBUG(Service_NFP, "called");
switch (device_state) {
case DeviceState::TagFound:
case DeviceState::TagNearby:
deactivate_event->Signal();
deactivate_event.writable->Signal();
device_state = DeviceState::Initialized;
break;
case DeviceState::SearchingForTag:
@@ -185,6 +189,7 @@ private:
void GetDeviceState(Kernel::HLERequestContext& ctx) {
LOG_DEBUG(Service_NFP, "called");
auto nfc_event = nfp_interface.GetNFCEvent();
if (!nfc_event->ShouldWait(Kernel::GetCurrentThread()) && !has_attached_handle) {
device_state = DeviceState::TagFound;
@@ -261,7 +266,7 @@ private:
IPC::ResponseBuilder rb{ctx, 2, 1};
rb.Push(RESULT_SUCCESS);
rb.PushCopyObjects(availability_change_event);
rb.PushCopyObjects(availability_change_event.readable);
}
void GetRegisterInfo(Kernel::HLERequestContext& ctx) {
@@ -316,13 +321,14 @@ private:
const u32 npad_id{0}; // Player 1 controller
State state{State::NonInitialized};
DeviceState device_state{DeviceState::Initialized};
Kernel::SharedPtr<Kernel::Event> deactivate_event;
Kernel::SharedPtr<Kernel::Event> availability_change_event;
Kernel::EventPair deactivate_event;
Kernel::EventPair availability_change_event;
const Module::Interface& nfp_interface;
};
void Module::Interface::CreateUserInterface(Kernel::HLERequestContext& ctx) {
LOG_DEBUG(Service_NFP, "called");
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(RESULT_SUCCESS);
rb.PushIpcInterface<IUser>(*this);
@@ -335,12 +341,14 @@ bool Module::Interface::LoadAmiibo(const std::vector<u8>& buffer) {
}
std::memcpy(&amiibo, buffer.data(), sizeof(amiibo));
nfc_tag_load->Signal();
nfc_tag_load.writable->Signal();
return true;
}
const Kernel::SharedPtr<Kernel::Event>& Module::Interface::GetNFCEvent() const {
return nfc_tag_load;
const Kernel::SharedPtr<Kernel::ReadableEvent>& Module::Interface::GetNFCEvent() const {
return nfc_tag_load.readable;
}
const Module::Interface::AmiiboFile& Module::Interface::GetAmiiboBuffer() const {
return amiibo;
}

View File

@@ -6,7 +6,8 @@
#include <array>
#include <vector>
#include "core/hle/kernel/event.h"
#include "core/hle/kernel/readable_event.h"
#include "core/hle/kernel/writable_event.h"
#include "core/hle/service/service.h"
namespace Service::NFP {
@@ -33,11 +34,11 @@ public:
void CreateUserInterface(Kernel::HLERequestContext& ctx);
bool LoadAmiibo(const std::vector<u8>& buffer);
const Kernel::SharedPtr<Kernel::Event>& GetNFCEvent() const;
const Kernel::SharedPtr<Kernel::ReadableEvent>& GetNFCEvent() const;
const AmiiboFile& GetAmiiboBuffer() const;
private:
Kernel::SharedPtr<Kernel::Event> nfc_tag_load{};
Kernel::EventPair nfc_tag_load{};
AmiiboFile amiibo{};
protected:

View File

@@ -4,7 +4,9 @@
#include "core/core.h"
#include "core/hle/ipc_helpers.h"
#include "core/hle/kernel/event.h"
#include "core/hle/kernel/kernel.h"
#include "core/hle/kernel/readable_event.h"
#include "core/hle/kernel/writable_event.h"
#include "core/hle/service/nifm/nifm.h"
#include "core/hle/service/service.h"
@@ -56,19 +58,23 @@ public:
RegisterHandlers(functions);
auto& kernel = Core::System::GetInstance().Kernel();
event1 = Kernel::Event::Create(kernel, Kernel::ResetType::OneShot, "IRequest:Event1");
event2 = Kernel::Event::Create(kernel, Kernel::ResetType::OneShot, "IRequest:Event2");
event1 = Kernel::WritableEvent::CreateEventPair(kernel, Kernel::ResetType::OneShot,
"IRequest:Event1");
event2 = Kernel::WritableEvent::CreateEventPair(kernel, Kernel::ResetType::OneShot,
"IRequest:Event2");
}
private:
void Submit(Kernel::HLERequestContext& ctx) {
LOG_WARNING(Service_NIFM, "(STUBBED) called");
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS);
}
void GetRequestState(Kernel::HLERequestContext& ctx) {
LOG_WARNING(Service_NIFM, "(STUBBED) called");
IPC::ResponseBuilder rb{ctx, 3};
rb.Push(RESULT_SUCCESS);
rb.Push<u32>(0);
@@ -76,30 +82,34 @@ private:
void GetResult(Kernel::HLERequestContext& ctx) {
LOG_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");
IPC::ResponseBuilder rb{ctx, 2, 2};
rb.Push(RESULT_SUCCESS);
rb.PushCopyObjects(event1, event2);
rb.PushCopyObjects(event1.readable, event2.readable);
}
void Cancel(Kernel::HLERequestContext& ctx) {
LOG_WARNING(Service_NIFM, "(STUBBED) called");
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS);
}
void SetConnectionConfirmationOption(Kernel::HLERequestContext& ctx) {
LOG_WARNING(Service_NIFM, "(STUBBED) called");
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS);
}
Kernel::SharedPtr<Kernel::Event> event1, event2;
Kernel::EventPair event1, event2;
};
class INetworkProfile final : public ServiceFramework<INetworkProfile> {
@@ -122,32 +132,36 @@ private:
void GetClientId(Kernel::HLERequestContext& ctx) {
static constexpr u32 client_id = 1;
LOG_WARNING(Service_NIFM, "(STUBBED) called");
IPC::ResponseBuilder rb{ctx, 4};
rb.Push(RESULT_SUCCESS);
rb.Push<u64>(client_id); // Client ID needs to be non zero otherwise it's considered invalid
}
void CreateScanRequest(Kernel::HLERequestContext& ctx) {
LOG_DEBUG(Service_NIFM, "called");
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(RESULT_SUCCESS);
rb.PushIpcInterface<IScanRequest>();
LOG_DEBUG(Service_NIFM, "called");
}
void CreateRequest(Kernel::HLERequestContext& ctx) {
LOG_DEBUG(Service_NIFM, "called");
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(RESULT_SUCCESS);
rb.PushIpcInterface<IRequest>();
LOG_DEBUG(Service_NIFM, "called");
}
void RemoveNetworkProfile(Kernel::HLERequestContext& ctx) {
LOG_WARNING(Service_NIFM, "(STUBBED) called");
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS);
}
void CreateTemporaryNetworkProfile(Kernel::HLERequestContext& ctx) {
LOG_DEBUG(Service_NIFM, "called");
ASSERT_MSG(ctx.GetReadBufferSize() == 0x17c, "NetworkProfileData is not the correct size");
u128 uuid{};
auto buffer = ctx.ReadBuffer();
@@ -158,23 +172,24 @@ private:
rb.Push(RESULT_SUCCESS);
rb.PushIpcInterface<INetworkProfile>();
rb.PushRaw<u128>(uuid);
LOG_DEBUG(Service_NIFM, "called");
}
void IsWirelessCommunicationEnabled(Kernel::HLERequestContext& ctx) {
LOG_WARNING(Service_NIFM, "(STUBBED) called");
IPC::ResponseBuilder rb{ctx, 3};
rb.Push(RESULT_SUCCESS);
rb.Push<u8>(0);
}
void IsEthernetCommunicationEnabled(Kernel::HLERequestContext& ctx) {
LOG_WARNING(Service_NIFM, "(STUBBED) called");
IPC::ResponseBuilder rb{ctx, 3};
rb.Push(RESULT_SUCCESS);
rb.Push<u8>(0);
}
void IsAnyInternetRequestAccepted(Kernel::HLERequestContext& ctx) {
LOG_WARNING(Service_NIFM, "(STUBBED) called");
IPC::ResponseBuilder rb{ctx, 3};
rb.Push(RESULT_SUCCESS);
rb.Push<u8>(0);
@@ -235,17 +250,19 @@ public:
}
void CreateGeneralServiceOld(Kernel::HLERequestContext& ctx) {
LOG_DEBUG(Service_NIFM, "called");
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(RESULT_SUCCESS);
rb.PushIpcInterface<IGeneralService>();
LOG_DEBUG(Service_NIFM, "called");
}
void CreateGeneralService(Kernel::HLERequestContext& ctx) {
LOG_DEBUG(Service_NIFM, "called");
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(RESULT_SUCCESS);
rb.PushIpcInterface<IGeneralService>();
LOG_DEBUG(Service_NIFM, "called");
}
};

View File

@@ -6,7 +6,9 @@
#include <ctime>
#include "core/core.h"
#include "core/hle/ipc_helpers.h"
#include "core/hle/kernel/event.h"
#include "core/hle/kernel/kernel.h"
#include "core/hle/kernel/readable_event.h"
#include "core/hle/kernel/writable_event.h"
#include "core/hle/service/nim/nim.h"
#include "core/hle/service/service.h"
#include "core/hle/service/sm/sm.h"
@@ -138,57 +140,61 @@ public:
RegisterHandlers(functions);
auto& kernel = Core::System::GetInstance().Kernel();
finished_event =
Kernel::Event::Create(kernel, Kernel::ResetType::OneShot,
"IEnsureNetworkClockAvailabilityService:FinishEvent");
finished_event = Kernel::WritableEvent::CreateEventPair(
kernel, Kernel::ResetType::OneShot,
"IEnsureNetworkClockAvailabilityService:FinishEvent");
}
private:
Kernel::SharedPtr<Kernel::Event> finished_event;
Kernel::EventPair finished_event;
void StartTask(Kernel::HLERequestContext& ctx) {
// No need to connect to the internet, just finish the task straight away.
finished_event->Signal();
LOG_DEBUG(Service_NIM, "called");
finished_event.writable->Signal();
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS);
LOG_DEBUG(Service_NIM, "called");
}
void GetFinishNotificationEvent(Kernel::HLERequestContext& ctx) {
LOG_DEBUG(Service_NIM, "called");
IPC::ResponseBuilder rb{ctx, 2, 1};
rb.Push(RESULT_SUCCESS);
rb.PushCopyObjects(finished_event);
LOG_DEBUG(Service_NIM, "called");
rb.PushCopyObjects(finished_event.readable);
}
void GetResult(Kernel::HLERequestContext& ctx) {
LOG_DEBUG(Service_NIM, "called");
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS);
LOG_DEBUG(Service_NIM, "called");
}
void Cancel(Kernel::HLERequestContext& ctx) {
finished_event->Clear();
LOG_DEBUG(Service_NIM, "called");
finished_event.writable->Clear();
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS);
LOG_DEBUG(Service_NIM, "called");
}
void IsProcessing(Kernel::HLERequestContext& ctx) {
LOG_DEBUG(Service_NIM, "called");
IPC::ResponseBuilder rb{ctx, 3};
rb.Push(RESULT_SUCCESS);
rb.PushRaw<u32>(0); // We instantly process the request
LOG_DEBUG(Service_NIM, "called");
}
void GetServerTime(Kernel::HLERequestContext& ctx) {
LOG_DEBUG(Service_NIM, "called");
const s64 server_time{std::chrono::duration_cast<std::chrono::seconds>(
std::chrono::system_clock::now().time_since_epoch())
.count()};
IPC::ResponseBuilder rb{ctx, 4};
rb.Push(RESULT_SUCCESS);
rb.PushRaw<s64>(server_time);
LOG_DEBUG(Service_NIM, "called");
}
};
@@ -208,23 +214,26 @@ public:
private:
void OpenEnsureNetworkClockAvailabilityService(Kernel::HLERequestContext& ctx) {
LOG_DEBUG(Service_NIM, "called");
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(RESULT_SUCCESS);
rb.PushIpcInterface<IEnsureNetworkClockAvailabilityService>();
LOG_DEBUG(Service_NIM, "called");
}
// TODO(ogniK): Do we need these?
void SuspendAutonomicTimeCorrection(Kernel::HLERequestContext& ctx) {
LOG_WARNING(Service_NIM, "(STUBBED) called");
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS);
LOG_WARNING(Service_NIM, "(STUBBED) called");
}
void ResumeAutonomicTimeCorrection(Kernel::HLERequestContext& ctx) {
LOG_WARNING(Service_NIM, "(STUBBED) called");
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS);
LOG_WARNING(Service_NIM, "(STUBBED) called");
}
};

View File

@@ -433,11 +433,11 @@ public:
private:
template <typename T>
void PushInterface(Kernel::HLERequestContext& ctx) {
LOG_DEBUG(Service_NS, "called");
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(RESULT_SUCCESS);
rb.PushIpcInterface<T>();
LOG_DEBUG(Service_NS, "called");
}
};
@@ -526,11 +526,11 @@ public:
private:
void OpenSystemUpdateControl(Kernel::HLERequestContext& ctx) {
LOG_DEBUG(Service_NS, "called");
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(RESULT_SUCCESS);
rb.PushIpcInterface<ISystemUpdateControl>();
LOG_DEBUG(Service_NS, "called");
}
};

View File

@@ -281,6 +281,7 @@ void PL_U::RequestLoad(Kernel::HLERequestContext& ctx) {
const u32 shared_font_type{rp.Pop<u32>()};
// Games don't call this so all fonts should be loaded
LOG_DEBUG(Service_NS, "called, shared_font_type={}", shared_font_type);
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS);
}
@@ -288,8 +289,8 @@ void PL_U::RequestLoad(Kernel::HLERequestContext& ctx) {
void PL_U::GetLoadState(Kernel::HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
const u32 font_id{rp.Pop<u32>()};
LOG_DEBUG(Service_NS, "called, font_id={}", font_id);
IPC::ResponseBuilder rb{ctx, 3};
rb.Push(RESULT_SUCCESS);
rb.Push<u32>(static_cast<u32>(LoadState::Done));
@@ -298,8 +299,8 @@ void PL_U::GetLoadState(Kernel::HLERequestContext& ctx) {
void PL_U::GetSize(Kernel::HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
const u32 font_id{rp.Pop<u32>()};
LOG_DEBUG(Service_NS, "called, font_id={}", font_id);
IPC::ResponseBuilder rb{ctx, 3};
rb.Push(RESULT_SUCCESS);
rb.Push<u32>(impl->GetSharedFontRegion(font_id).size);
@@ -308,8 +309,8 @@ void PL_U::GetSize(Kernel::HLERequestContext& ctx) {
void PL_U::GetSharedMemoryAddressOffset(Kernel::HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
const u32 font_id{rp.Pop<u32>()};
LOG_DEBUG(Service_NS, "called, font_id={}", font_id);
IPC::ResponseBuilder rb{ctx, 3};
rb.Push(RESULT_SUCCESS);
rb.Push<u32>(impl->GetSharedFontRegion(font_id).offset);
@@ -317,6 +318,7 @@ void PL_U::GetSharedMemoryAddressOffset(Kernel::HLERequestContext& ctx) {
void PL_U::GetSharedMemoryNativeHandle(Kernel::HLERequestContext& ctx) {
// Map backing memory for the font data
LOG_DEBUG(Service_NS, "called");
Core::CurrentProcess()->VMManager().MapMemoryBlock(SHARED_FONT_MEM_VADDR, impl->shared_font, 0,
SHARED_FONT_MEM_SIZE,
Kernel::MemoryState::Shared);
@@ -328,7 +330,6 @@ void PL_U::GetSharedMemoryNativeHandle(Kernel::HLERequestContext& ctx) {
Kernel::MemoryPermission::Read, SHARED_FONT_MEM_VADDR, Kernel::MemoryRegion::BASE,
"PL_U:shared_font_mem");
LOG_DEBUG(Service_NS, "called");
IPC::ResponseBuilder rb{ctx, 2, 1};
rb.Push(RESULT_SUCCESS);
rb.PushCopyObjects(impl->shared_font_mem);
@@ -338,6 +339,7 @@ void PL_U::GetSharedFontInOrderOfPriority(Kernel::HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
const u64 language_code{rp.Pop<u64>()}; // TODO(ogniK): Find out what this is used for
LOG_DEBUG(Service_NS, "called, language_code={:X}", language_code);
IPC::ResponseBuilder rb{ctx, 4};
std::vector<u32> font_codes;
std::vector<u32> font_offsets;

View File

@@ -54,6 +54,7 @@ u32 nvhost_as_gpu::InitalizeEx(const std::vector<u8>& input, std::vector<u8>& ou
IoctlInitalizeEx params{};
std::memcpy(&params, input.data(), input.size());
LOG_WARNING(Service_NVDRV, "(STUBBED) called, big_page_size=0x{:X}", params.big_page_size);
return 0;
}
@@ -191,6 +192,7 @@ u32 nvhost_as_gpu::BindChannel(const std::vector<u8>& input, std::vector<u8>& ou
IoctlBindChannel params{};
std::memcpy(&params, input.data(), input.size());
LOG_DEBUG(Service_NVDRV, "called, fd={:X}", params.fd);
channel = params.fd;
return 0;
}

View File

@@ -103,6 +103,7 @@ u32 nvhost_ctrl_gpu::GetTPCMasks(const std::vector<u8>& input, std::vector<u8>&
u32 nvhost_ctrl_gpu::GetActiveSlotMask(const std::vector<u8>& input, std::vector<u8>& output) {
LOG_DEBUG(Service_NVDRV, "called");
IoctlActiveSlotMask params{};
if (input.size() > 0) {
std::memcpy(&params, input.data(), input.size());
@@ -115,6 +116,7 @@ u32 nvhost_ctrl_gpu::GetActiveSlotMask(const std::vector<u8>& input, std::vector
u32 nvhost_ctrl_gpu::ZCullGetCtxSize(const std::vector<u8>& input, std::vector<u8>& output) {
LOG_DEBUG(Service_NVDRV, "called");
IoctlZcullGetCtxSize params{};
if (input.size() > 0) {
std::memcpy(&params, input.data(), input.size());
@@ -126,6 +128,7 @@ u32 nvhost_ctrl_gpu::ZCullGetCtxSize(const std::vector<u8>& input, std::vector<u
u32 nvhost_ctrl_gpu::ZCullGetInfo(const std::vector<u8>& input, std::vector<u8>& output) {
LOG_DEBUG(Service_NVDRV, "called");
IoctlNvgpuGpuZcullGetInfoArgs params{};
if (input.size() > 0) {
@@ -148,6 +151,7 @@ u32 nvhost_ctrl_gpu::ZCullGetInfo(const std::vector<u8>& input, std::vector<u8>&
u32 nvhost_ctrl_gpu::ZBCSetTable(const std::vector<u8>& input, std::vector<u8>& output) {
LOG_WARNING(Service_NVDRV, "(STUBBED) called");
IoctlZbcSetTable params{};
std::memcpy(&params, input.data(), input.size());
// TODO(ogniK): What does this even actually do?
@@ -157,6 +161,7 @@ u32 nvhost_ctrl_gpu::ZBCSetTable(const std::vector<u8>& input, std::vector<u8>&
u32 nvhost_ctrl_gpu::ZBCQueryTable(const std::vector<u8>& input, std::vector<u8>& output) {
LOG_WARNING(Service_NVDRV, "(STUBBED) called");
IoctlZbcQueryTable params{};
std::memcpy(&params, input.data(), input.size());
// TODO : To implement properly
@@ -166,6 +171,7 @@ u32 nvhost_ctrl_gpu::ZBCQueryTable(const std::vector<u8>& input, std::vector<u8>
u32 nvhost_ctrl_gpu::FlushL2(const std::vector<u8>& input, std::vector<u8>& output) {
LOG_WARNING(Service_NVDRV, "(STUBBED) called");
IoctlFlushL2 params{};
std::memcpy(&params, input.data(), input.size());
// TODO : To implement properly
@@ -175,6 +181,7 @@ u32 nvhost_ctrl_gpu::FlushL2(const std::vector<u8>& input, std::vector<u8>& outp
u32 nvhost_ctrl_gpu::GetGpuTime(const std::vector<u8>& input, std::vector<u8>& output) {
LOG_DEBUG(Service_NVDRV, "called");
IoctlGetGpuTime params{};
std::memcpy(&params, input.data(), input.size());
params.gpu_time = CoreTiming::cyclesToNs(CoreTiming::GetTicks());

View File

@@ -8,7 +8,6 @@
#include "core/core.h"
#include "core/hle/service/nvdrv/devices/nvhost_gpu.h"
#include "core/memory.h"
#include "video_core/command_processor.h"
#include "video_core/gpu.h"
#include "video_core/memory_manager.h"
@@ -61,12 +60,14 @@ u32 nvhost_gpu::SetNVMAPfd(const std::vector<u8>& input, std::vector<u8>& output
IoctlSetNvmapFD params{};
std::memcpy(&params, input.data(), input.size());
LOG_DEBUG(Service_NVDRV, "called, fd={}", params.nvmap_fd);
nvmap_fd = params.nvmap_fd;
return 0;
}
u32 nvhost_gpu::SetClientData(const std::vector<u8>& input, std::vector<u8>& output) {
LOG_DEBUG(Service_NVDRV, "called");
IoctlClientData params{};
std::memcpy(&params, input.data(), input.size());
user_data = params.data;
@@ -75,6 +76,7 @@ u32 nvhost_gpu::SetClientData(const std::vector<u8>& input, std::vector<u8>& out
u32 nvhost_gpu::GetClientData(const std::vector<u8>& input, std::vector<u8>& output) {
LOG_DEBUG(Service_NVDRV, "called");
IoctlClientData params{};
std::memcpy(&params, input.data(), input.size());
params.data = user_data;
@@ -86,6 +88,7 @@ u32 nvhost_gpu::ZCullBind(const std::vector<u8>& input, std::vector<u8>& output)
std::memcpy(&zcull_params, input.data(), input.size());
LOG_DEBUG(Service_NVDRV, "called, gpu_va={:X}, mode={:X}", zcull_params.gpu_va,
zcull_params.mode);
std::memcpy(output.data(), &zcull_params, output.size());
return 0;
}
@@ -95,6 +98,7 @@ u32 nvhost_gpu::SetErrorNotifier(const std::vector<u8>& input, std::vector<u8>&
std::memcpy(&params, input.data(), input.size());
LOG_WARNING(Service_NVDRV, "(STUBBED) called, offset={:X}, size={:X}, mem={:X}", params.offset,
params.size, params.mem);
std::memcpy(output.data(), &params, output.size());
return 0;
}
@@ -102,6 +106,7 @@ u32 nvhost_gpu::SetErrorNotifier(const std::vector<u8>& input, std::vector<u8>&
u32 nvhost_gpu::SetChannelPriority(const std::vector<u8>& input, std::vector<u8>& output) {
std::memcpy(&channel_priority, input.data(), input.size());
LOG_DEBUG(Service_NVDRV, "(STUBBED) called, priority={:X}", channel_priority);
return 0;
}
@@ -113,6 +118,7 @@ u32 nvhost_gpu::AllocGPFIFOEx2(const std::vector<u8>& input, std::vector<u8>& ou
"unk1={:X}, unk2={:X}, unk3={:X}",
params.num_entries, params.flags, params.unk0, params.unk1, params.unk2,
params.unk3);
params.fence_out.id = 0;
params.fence_out.value = 0;
std::memcpy(output.data(), &params, output.size());
@@ -124,11 +130,18 @@ u32 nvhost_gpu::AllocateObjectContext(const std::vector<u8>& input, std::vector<
std::memcpy(&params, input.data(), input.size());
LOG_WARNING(Service_NVDRV, "(STUBBED) called, class_num={:X}, flags={:X}", params.class_num,
params.flags);
params.obj_id = 0x0;
std::memcpy(output.data(), &params, output.size());
return 0;
}
static void PushGPUEntries(Tegra::CommandList&& entries) {
auto& dma_pusher{Core::System::GetInstance().GPU().DmaPusher()};
dma_pusher.Push(std::move(entries));
dma_pusher.DispatchCalls();
}
u32 nvhost_gpu::SubmitGPFIFO(const std::vector<u8>& input, std::vector<u8>& output) {
if (input.size() < sizeof(IoctlSubmitGpfifo)) {
UNIMPLEMENTED();
@@ -142,11 +155,11 @@ u32 nvhost_gpu::SubmitGPFIFO(const std::vector<u8>& input, std::vector<u8>& outp
params.num_entries * sizeof(Tegra::CommandListHeader),
"Incorrect input size");
std::vector<Tegra::CommandListHeader> entries(params.num_entries);
Tegra::CommandList entries(params.num_entries);
std::memcpy(entries.data(), &input[sizeof(IoctlSubmitGpfifo)],
params.num_entries * sizeof(Tegra::CommandListHeader));
Core::System::GetInstance().GPU().ProcessCommandLists(entries);
PushGPUEntries(std::move(entries));
params.fence_out.id = 0;
params.fence_out.value = 0;
@@ -163,11 +176,11 @@ u32 nvhost_gpu::KickoffPB(const std::vector<u8>& input, std::vector<u8>& output)
LOG_WARNING(Service_NVDRV, "(STUBBED) called, gpfifo={:X}, num_entries={:X}, flags={:X}",
params.address, params.num_entries, params.flags);
std::vector<Tegra::CommandListHeader> entries(params.num_entries);
Tegra::CommandList entries(params.num_entries);
Memory::ReadBlock(params.address, entries.data(),
params.num_entries * sizeof(Tegra::CommandListHeader));
Core::System::GetInstance().GPU().ProcessCommandLists(entries);
PushGPUEntries(std::move(entries));
params.fence_out.id = 0;
params.fence_out.value = 0;
@@ -179,6 +192,7 @@ u32 nvhost_gpu::GetWaitbase(const std::vector<u8>& input, std::vector<u8>& outpu
IoctlGetWaitbase params{};
std::memcpy(&params, input.data(), sizeof(IoctlGetWaitbase));
LOG_INFO(Service_NVDRV, "called, unknown=0x{:X}", params.unknown);
params.value = 0; // Seems to be hard coded at 0
std::memcpy(output.data(), &params, output.size());
return 0;
@@ -188,6 +202,7 @@ u32 nvhost_gpu::ChannelSetTimeout(const std::vector<u8>& input, std::vector<u8>&
IoctlChannelSetTimeout params{};
std::memcpy(&params, input.data(), sizeof(IoctlChannelSetTimeout));
LOG_INFO(Service_NVDRV, "called, timeout=0x{:X}", params.timeout);
return 0;
}

View File

@@ -30,6 +30,7 @@ u32 nvhost_nvdec::SetNVMAPfd(const std::vector<u8>& input, std::vector<u8>& outp
IoctlSetNvmapFD params{};
std::memcpy(&params, input.data(), input.size());
LOG_DEBUG(Service_NVDRV, "called, fd={}", params.nvmap_fd);
nvmap_fd = params.nvmap_fd;
return 0;
}

View File

@@ -30,6 +30,7 @@ u32 nvhost_nvjpg::SetNVMAPfd(const std::vector<u8>& input, std::vector<u8>& outp
IoctlSetNvmapFD params{};
std::memcpy(&params, input.data(), input.size());
LOG_DEBUG(Service_NVDRV, "called, fd={}", params.nvmap_fd);
nvmap_fd = params.nvmap_fd;
return 0;
}

View File

@@ -30,6 +30,7 @@ u32 nvhost_vic::SetNVMAPfd(const std::vector<u8>& input, std::vector<u8>& output
IoctlSetNvmapFD params{};
std::memcpy(&params, input.data(), input.size());
LOG_DEBUG(Service_NVDRV, "called, fd={}", params.nvmap_fd);
nvmap_fd = params.nvmap_fd;
return 0;
}

View File

@@ -54,6 +54,7 @@ u32 nvmap::IocCreate(const std::vector<u8>& input, std::vector<u8>& output) {
LOG_DEBUG(Service_NVDRV, "size=0x{:08X}", params.size);
if (!params.size) {
LOG_ERROR(Service_NVDRV, "Size is 0");
return static_cast<u32>(NvErrCodes::InvalidValue);
}
// Create a new nvmap object and obtain a handle to it.
@@ -78,10 +79,12 @@ u32 nvmap::IocAlloc(const std::vector<u8>& input, std::vector<u8>& output) {
LOG_DEBUG(Service_NVDRV, "called, addr={:X}", params.addr);
if (!params.handle) {
LOG_ERROR(Service_NVDRV, "Handle is 0");
return static_cast<u32>(NvErrCodes::InvalidValue);
}
if ((params.align - 1) & params.align) {
LOG_ERROR(Service_NVDRV, "Incorrect alignment used, alignment={:08X}", params.align);
return static_cast<u32>(NvErrCodes::InvalidValue);
}
@@ -92,10 +95,12 @@ u32 nvmap::IocAlloc(const std::vector<u8>& input, std::vector<u8>& output) {
auto object = GetObject(params.handle);
if (!object) {
LOG_ERROR(Service_NVDRV, "Object does not exist, handle={:08X}", params.handle);
return static_cast<u32>(NvErrCodes::InvalidValue);
}
if (object->status == Object::Status::Allocated) {
LOG_ERROR(Service_NVDRV, "Object is already allocated, handle={:08X}", params.handle);
return static_cast<u32>(NvErrCodes::OperationNotPermitted);
}
@@ -116,11 +121,13 @@ u32 nvmap::IocGetId(const std::vector<u8>& input, std::vector<u8>& output) {
LOG_WARNING(Service_NVDRV, "called");
if (!params.handle) {
LOG_ERROR(Service_NVDRV, "Handle is zero");
return static_cast<u32>(NvErrCodes::InvalidValue);
}
auto object = GetObject(params.handle);
if (!object) {
LOG_ERROR(Service_NVDRV, "Object does not exist, handle={:08X}", params.handle);
return static_cast<u32>(NvErrCodes::OperationNotPermitted);
}
@@ -139,11 +146,13 @@ u32 nvmap::IocFromId(const std::vector<u8>& input, std::vector<u8>& output) {
auto itr = std::find_if(handles.begin(), handles.end(),
[&](const auto& entry) { return entry.second->id == params.id; });
if (itr == handles.end()) {
LOG_ERROR(Service_NVDRV, "Object does not exist, handle={:08X}", params.handle);
return static_cast<u32>(NvErrCodes::InvalidValue);
}
auto& object = itr->second;
if (object->status != Object::Status::Allocated) {
LOG_ERROR(Service_NVDRV, "Object is not allocated, handle={:08X}", params.handle);
return static_cast<u32>(NvErrCodes::InvalidValue);
}
@@ -166,10 +175,12 @@ u32 nvmap::IocParam(const std::vector<u8>& input, std::vector<u8>& output) {
auto object = GetObject(params.handle);
if (!object) {
LOG_ERROR(Service_NVDRV, "Object does not exist, handle={:08X}", params.handle);
return static_cast<u32>(NvErrCodes::InvalidValue);
}
if (object->status != Object::Status::Allocated) {
LOG_ERROR(Service_NVDRV, "Object is not allocated, handle={:08X}", params.handle);
return static_cast<u32>(NvErrCodes::OperationNotPermitted);
}
@@ -209,9 +220,14 @@ u32 nvmap::IocFree(const std::vector<u8>& input, std::vector<u8>& output) {
auto itr = handles.find(params.handle);
if (itr == handles.end()) {
LOG_ERROR(Service_NVDRV, "Object does not exist, handle={:08X}", params.handle);
return static_cast<u32>(NvErrCodes::InvalidValue);
}
if (!itr->second->refcount) {
LOG_ERROR(
Service_NVDRV,
"There is no references to this object. The object is already freed. handle={:08X}",
params.handle);
return static_cast<u32>(NvErrCodes::InvalidValue);
}

View File

@@ -6,7 +6,9 @@
#include "common/logging/log.h"
#include "core/core.h"
#include "core/hle/ipc_helpers.h"
#include "core/hle/kernel/event.h"
#include "core/hle/kernel/kernel.h"
#include "core/hle/kernel/readable_event.h"
#include "core/hle/kernel/writable_event.h"
#include "core/hle/service/nvdrv/interface.h"
#include "core/hle/service/nvdrv/nvdrv.h"
@@ -55,6 +57,7 @@ void NVDRV::Close(Kernel::HLERequestContext& ctx) {
void NVDRV::Initialize(Kernel::HLERequestContext& ctx) {
LOG_WARNING(Service_NVDRV, "(STUBBED) called");
IPC::ResponseBuilder rb{ctx, 3};
rb.Push(RESULT_SUCCESS);
rb.Push<u32>(0);
@@ -68,15 +71,15 @@ void NVDRV::QueryEvent(Kernel::HLERequestContext& ctx) {
IPC::ResponseBuilder rb{ctx, 3, 1};
rb.Push(RESULT_SUCCESS);
rb.PushCopyObjects(query_event);
rb.PushCopyObjects(query_event.readable);
rb.Push<u32>(0);
}
void NVDRV::SetClientPID(Kernel::HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
pid = rp.Pop<u64>();
LOG_WARNING(Service_NVDRV, "(STUBBED) called, pid=0x{:X}", pid);
IPC::ResponseBuilder rb{ctx, 3};
rb.Push(RESULT_SUCCESS);
rb.Push<u32>(0);
@@ -84,6 +87,23 @@ void NVDRV::SetClientPID(Kernel::HLERequestContext& ctx) {
void NVDRV::FinishInitialize(Kernel::HLERequestContext& ctx) {
LOG_WARNING(Service_NVDRV, "(STUBBED) called");
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS);
}
void NVDRV::GetStatus(Kernel::HLERequestContext& ctx) {
LOG_WARNING(Service_NVDRV, "(STUBBED) called");
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS);
}
void NVDRV::DumpGraphicsMemoryInfo(Kernel::HLERequestContext& ctx) {
// According to SwitchBrew, this has no inputs and no outputs, so effectively does nothing on
// retail hardware.
LOG_DEBUG(Service_NVDRV, "called");
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS);
}
@@ -97,10 +117,10 @@ NVDRV::NVDRV(std::shared_ptr<Module> nvdrv, const char* name)
{3, &NVDRV::Initialize, "Initialize"},
{4, &NVDRV::QueryEvent, "QueryEvent"},
{5, nullptr, "MapSharedMem"},
{6, nullptr, "GetStatus"},
{6, &NVDRV::GetStatus, "GetStatus"},
{7, nullptr, "ForceSetClientPID"},
{8, &NVDRV::SetClientPID, "SetClientPID"},
{9, nullptr, "DumpGraphicsMemoryInfo"},
{9, &NVDRV::DumpGraphicsMemoryInfo, "DumpGraphicsMemoryInfo"},
{10, nullptr, "InitializeDevtools"},
{11, &NVDRV::Ioctl, "Ioctl2"},
{12, nullptr, "Ioctl3"},
@@ -109,7 +129,8 @@ NVDRV::NVDRV(std::shared_ptr<Module> nvdrv, const char* name)
RegisterHandlers(functions);
auto& kernel = Core::System::GetInstance().Kernel();
query_event = Kernel::Event::Create(kernel, Kernel::ResetType::OneShot, "NVDRV::query_event");
query_event = Kernel::WritableEvent::CreateEventPair(kernel, Kernel::ResetType::OneShot,
"NVDRV::query_event");
}
NVDRV::~NVDRV() = default;

View File

@@ -5,10 +5,13 @@
#pragma once
#include <memory>
#include "core/hle/kernel/event.h"
#include "core/hle/service/nvdrv/nvdrv.h"
#include "core/hle/service/service.h"
namespace Kernel {
class WritableEvent;
}
namespace Service::Nvidia {
class NVDRV final : public ServiceFramework<NVDRV> {
@@ -24,12 +27,14 @@ private:
void QueryEvent(Kernel::HLERequestContext& ctx);
void SetClientPID(Kernel::HLERequestContext& ctx);
void FinishInitialize(Kernel::HLERequestContext& ctx);
void GetStatus(Kernel::HLERequestContext& ctx);
void DumpGraphicsMemoryInfo(Kernel::HLERequestContext& ctx);
std::shared_ptr<Module> nvdrv;
u64 pid{};
Kernel::SharedPtr<Kernel::Event> query_event;
Kernel::EventPair query_event;
};
} // namespace Service::Nvidia

View File

@@ -7,28 +7,31 @@
#include "common/assert.h"
#include "common/logging/log.h"
#include "core/core.h"
#include "core/hle/kernel/kernel.h"
#include "core/hle/kernel/readable_event.h"
#include "core/hle/kernel/writable_event.h"
#include "core/hle/service/nvflinger/buffer_queue.h"
namespace Service::NVFlinger {
BufferQueue::BufferQueue(u32 id, u64 layer_id) : id(id), layer_id(layer_id) {
auto& kernel = Core::System::GetInstance().Kernel();
buffer_wait_event =
Kernel::Event::Create(kernel, Kernel::ResetType::Sticky, "BufferQueue NativeHandle");
buffer_wait_event = Kernel::WritableEvent::CreateEventPair(kernel, Kernel::ResetType::Sticky,
"BufferQueue NativeHandle");
}
BufferQueue::~BufferQueue() = default;
void BufferQueue::SetPreallocatedBuffer(u32 slot, const IGBPBuffer& igbp_buffer) {
LOG_WARNING(Service, "Adding graphics buffer {}", slot);
Buffer buffer{};
buffer.slot = slot;
buffer.igbp_buffer = igbp_buffer;
buffer.status = Buffer::Status::Free;
LOG_WARNING(Service, "Adding graphics buffer {}", slot);
queue.emplace_back(buffer);
buffer_wait_event->Signal();
buffer_wait_event.writable->Signal();
}
std::optional<u32> BufferQueue::DequeueBuffer(u32 width, u32 height) {
@@ -87,11 +90,12 @@ void BufferQueue::ReleaseBuffer(u32 slot) {
ASSERT(itr->status == Buffer::Status::Acquired);
itr->status = Buffer::Status::Free;
buffer_wait_event->Signal();
buffer_wait_event.writable->Signal();
}
u32 BufferQueue::Query(QueryType type) {
LOG_WARNING(Service, "(STUBBED) called type={}", static_cast<u32>(type));
switch (type) {
case QueryType::NativeWindowFormat:
// TODO(Subv): Use an enum for this
@@ -103,4 +107,12 @@ u32 BufferQueue::Query(QueryType type) {
return 0;
}
Kernel::SharedPtr<Kernel::WritableEvent> BufferQueue::GetWritableBufferWaitEvent() const {
return buffer_wait_event.writable;
}
Kernel::SharedPtr<Kernel::ReadableEvent> BufferQueue::GetBufferWaitEvent() const {
return buffer_wait_event.readable;
}
} // namespace Service::NVFlinger

View File

@@ -10,7 +10,8 @@
#include "common/common_funcs.h"
#include "common/math_util.h"
#include "common/swap.h"
#include "core/hle/kernel/event.h"
#include "core/hle/kernel/object.h"
#include "core/hle/kernel/writable_event.h"
namespace CoreTiming {
struct EventType;
@@ -86,16 +87,16 @@ public:
return id;
}
Kernel::SharedPtr<Kernel::Event> GetBufferWaitEvent() const {
return buffer_wait_event;
}
Kernel::SharedPtr<Kernel::WritableEvent> GetWritableBufferWaitEvent() const;
Kernel::SharedPtr<Kernel::ReadableEvent> GetBufferWaitEvent() const;
private:
u32 id;
u64 layer_id;
std::vector<Buffer> queue;
Kernel::SharedPtr<Kernel::Event> buffer_wait_event;
Kernel::EventPair buffer_wait_event;
};
} // namespace Service::NVFlinger

View File

@@ -13,6 +13,9 @@
#include "core/core.h"
#include "core/core_timing.h"
#include "core/core_timing_util.h"
#include "core/hle/kernel/kernel.h"
#include "core/hle/kernel/readable_event.h"
#include "core/hle/kernel/writable_event.h"
#include "core/hle/service/nvdrv/devices/nvdisp_disp0.h"
#include "core/hle/service/nvdrv/nvdrv.h"
#include "core/hle/service/nvflinger/buffer_queue.h"
@@ -83,9 +86,8 @@ u32 NVFlinger::GetBufferQueueId(u64 display_id, u64 layer_id) {
return layer.buffer_queue->GetId();
}
Kernel::SharedPtr<Kernel::Event> NVFlinger::GetVsyncEvent(u64 display_id) {
const auto& display = GetDisplay(display_id);
return display.vsync_event;
Kernel::SharedPtr<Kernel::ReadableEvent> NVFlinger::GetVsyncEvent(u64 display_id) {
return GetDisplay(display_id).vsync_event.readable;
}
std::shared_ptr<BufferQueue> NVFlinger::GetBufferQueue(u32 id) const {
@@ -117,7 +119,7 @@ Layer& NVFlinger::GetLayer(u64 display_id, u64 layer_id) {
void NVFlinger::Compose() {
for (auto& display : displays) {
// Trigger vsync for this display at the end of drawing
SCOPE_EXIT({ display.vsync_event->Signal(); });
SCOPE_EXIT({ display.vsync_event.writable->Signal(); });
// Don't do anything for displays without layers.
if (display.layers.empty())
@@ -164,7 +166,8 @@ Layer::~Layer() = default;
Display::Display(u64 id, std::string name) : id(id), name(std::move(name)) {
auto& kernel = Core::System::GetInstance().Kernel();
vsync_event = Kernel::Event::Create(kernel, Kernel::ResetType::Pulse, "Display VSync Event");
vsync_event = Kernel::WritableEvent::CreateEventPair(kernel, Kernel::ResetType::Pulse,
fmt::format("Display VSync Event {}", id));
}
Display::~Display() = default;

View File

@@ -10,12 +10,17 @@
#include <vector>
#include "common/common_types.h"
#include "core/hle/kernel/event.h"
#include "core/hle/kernel/object.h"
namespace CoreTiming {
struct EventType;
}
namespace Kernel {
class ReadableEvent;
class WritableEvent;
} // namespace Kernel
namespace Service::Nvidia {
class Module;
}
@@ -40,7 +45,7 @@ struct Display {
std::string name;
std::vector<Layer> layers;
Kernel::SharedPtr<Kernel::Event> vsync_event;
Kernel::EventPair vsync_event;
};
class NVFlinger final {
@@ -61,7 +66,7 @@ public:
u32 GetBufferQueueId(u64 display_id, u64 layer_id);
/// Gets the vsync event for the specified display.
Kernel::SharedPtr<Kernel::Event> GetVsyncEvent(u64 display_id);
Kernel::SharedPtr<Kernel::ReadableEvent> GetVsyncEvent(u64 display_id);
/// Obtains a buffer queue identified by the id.
std::shared_ptr<BufferQueue> GetBufferQueue(u32 id) const;

View File

@@ -114,29 +114,33 @@ public:
private:
void Initialize(Kernel::HLERequestContext& ctx) {
LOG_WARNING(Service_PCTL, "(STUBBED) called");
IPC::ResponseBuilder rb{ctx, 2, 0, 0};
rb.Push(RESULT_SUCCESS);
}
void CheckFreeCommunicationPermission(Kernel::HLERequestContext& ctx) {
LOG_WARNING(Service_PCTL, "(STUBBED) called");
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS);
}
};
void Module::Interface::CreateService(Kernel::HLERequestContext& ctx) {
LOG_DEBUG(Service_PCTL, "called");
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(RESULT_SUCCESS);
rb.PushIpcInterface<IParentalControlService>();
LOG_DEBUG(Service_PCTL, "called");
}
void Module::Interface::CreateServiceWithoutInitialize(Kernel::HLERequestContext& ctx) {
LOG_DEBUG(Service_PCTL, "called");
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(RESULT_SUCCESS);
rb.PushIpcInterface<IParentalControlService>();
LOG_DEBUG(Service_PCTL, "called");
}
Module::Interface::Interface(std::shared_ptr<Module> module, const char* name)

View File

@@ -20,11 +20,11 @@ public:
private:
void GetBootMode(Kernel::HLERequestContext& ctx) {
LOG_DEBUG(Service_PM, "called");
IPC::ResponseBuilder rb{ctx, 3};
rb.Push(RESULT_SUCCESS);
rb.Push<u32>(static_cast<u32>(SystemBootMode::Normal)); // Normal boot mode
LOG_DEBUG(Service_PM, "called");
}
};

View File

@@ -61,11 +61,11 @@ public:
private:
void GetPmModule(Kernel::HLERequestContext& ctx) {
LOG_DEBUG(Service_PSC, "called");
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(RESULT_SUCCESS);
rb.PushIpcInterface<IPmModule>();
LOG_DEBUG(Service_PSC, "called");
}
};

View File

@@ -35,6 +35,8 @@ constexpr std::array<LanguageCode, 17> available_language_codes = {{
constexpr std::size_t pre4_0_0_max_entries = 0xF;
constexpr std::size_t post4_0_0_max_entries = 0x40;
constexpr ResultCode ERR_INVALID_LANGUAGE{ErrorModule::Settings, 625};
LanguageCode GetLanguageCodeFromIndex(std::size_t index) {
return available_language_codes.at(index);
}
@@ -49,38 +51,54 @@ static std::array<LanguageCode, size> MakeLanguageCodeSubset() {
static void PushResponseLanguageCode(Kernel::HLERequestContext& ctx, std::size_t max_size) {
IPC::ResponseBuilder rb{ctx, 3};
rb.Push(RESULT_SUCCESS);
if (available_language_codes.size() > max_size)
if (available_language_codes.size() > max_size) {
rb.Push(static_cast<u32>(max_size));
else
} else {
rb.Push(static_cast<u32>(available_language_codes.size()));
}
}
void SET::GetAvailableLanguageCodes(Kernel::HLERequestContext& ctx) {
if (available_language_codes.size() > pre4_0_0_max_entries)
ctx.WriteBuffer(MakeLanguageCodeSubset<pre4_0_0_max_entries>());
else
ctx.WriteBuffer(available_language_codes);
PushResponseLanguageCode(ctx, pre4_0_0_max_entries);
LOG_DEBUG(Service_SET, "called");
if (available_language_codes.size() > pre4_0_0_max_entries) {
ctx.WriteBuffer(MakeLanguageCodeSubset<pre4_0_0_max_entries>());
} else {
ctx.WriteBuffer(available_language_codes);
}
PushResponseLanguageCode(ctx, pre4_0_0_max_entries);
}
void SET::MakeLanguageCode(Kernel::HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
const auto index = rp.Pop<u32>();
if (index >= available_language_codes.size()) {
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(ERR_INVALID_LANGUAGE);
return;
}
IPC::ResponseBuilder rb{ctx, 4};
rb.Push(RESULT_SUCCESS);
rb.PushEnum(available_language_codes[index]);
}
void SET::GetAvailableLanguageCodes2(Kernel::HLERequestContext& ctx) {
if (available_language_codes.size() > post4_0_0_max_entries)
ctx.WriteBuffer(MakeLanguageCodeSubset<post4_0_0_max_entries>());
else
ctx.WriteBuffer(available_language_codes);
PushResponseLanguageCode(ctx, post4_0_0_max_entries);
LOG_DEBUG(Service_SET, "called");
if (available_language_codes.size() > post4_0_0_max_entries) {
ctx.WriteBuffer(MakeLanguageCodeSubset<post4_0_0_max_entries>());
} else {
ctx.WriteBuffer(available_language_codes);
}
PushResponseLanguageCode(ctx, post4_0_0_max_entries);
}
void SET::GetAvailableLanguageCodeCount(Kernel::HLERequestContext& ctx) {
PushResponseLanguageCode(ctx, pre4_0_0_max_entries);
LOG_DEBUG(Service_SET, "called");
PushResponseLanguageCode(ctx, pre4_0_0_max_entries);
}
void SET::GetAvailableLanguageCodeCount2(Kernel::HLERequestContext& ctx) {
@@ -90,18 +108,18 @@ void SET::GetAvailableLanguageCodeCount2(Kernel::HLERequestContext& ctx) {
}
void SET::GetLanguageCode(Kernel::HLERequestContext& ctx) {
LOG_DEBUG(Service_SET, "called {}", Settings::values.language_index);
IPC::ResponseBuilder rb{ctx, 4};
rb.Push(RESULT_SUCCESS);
rb.Push(static_cast<u64>(available_language_codes[Settings::values.language_index]));
LOG_DEBUG(Service_SET, "called {}", Settings::values.language_index);
rb.PushEnum(available_language_codes[Settings::values.language_index]);
}
SET::SET() : ServiceFramework("set") {
static const FunctionInfo functions[] = {
{0, &SET::GetLanguageCode, "GetLanguageCode"},
{1, &SET::GetAvailableLanguageCodes, "GetAvailableLanguageCodes"},
{2, nullptr, "MakeLanguageCode"},
{2, &SET::MakeLanguageCode, "MakeLanguageCode"},
{3, &SET::GetAvailableLanguageCodeCount, "GetAvailableLanguageCodeCount"},
{4, nullptr, "GetRegionCode"},
{5, &SET::GetAvailableLanguageCodes2, "GetAvailableLanguageCodes2"},

View File

@@ -38,6 +38,7 @@ public:
private:
void GetLanguageCode(Kernel::HLERequestContext& ctx);
void GetAvailableLanguageCodes(Kernel::HLERequestContext& ctx);
void MakeLanguageCode(Kernel::HLERequestContext& ctx);
void GetAvailableLanguageCodes2(Kernel::HLERequestContext& ctx);
void GetAvailableLanguageCodeCount(Kernel::HLERequestContext& ctx);
void GetAvailableLanguageCodeCount2(Kernel::HLERequestContext& ctx);

View File

@@ -10,22 +10,22 @@
namespace Service::Set {
void SET_SYS::GetColorSetId(Kernel::HLERequestContext& ctx) {
LOG_DEBUG(Service_SET, "called");
IPC::ResponseBuilder rb{ctx, 3};
rb.Push(RESULT_SUCCESS);
rb.PushEnum(color_set);
LOG_DEBUG(Service_SET, "called");
}
void SET_SYS::SetColorSetId(Kernel::HLERequestContext& ctx) {
LOG_DEBUG(Service_SET, "called");
IPC::RequestParser rp{ctx};
color_set = rp.PopEnum<ColorSet>();
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS);
LOG_DEBUG(Service_SET, "called");
}
SET_SYS::SET_SYS() : ServiceFramework("set:sys") {

View File

@@ -14,25 +14,26 @@ namespace Service::SM {
void Controller::ConvertSessionToDomain(Kernel::HLERequestContext& ctx) {
ASSERT_MSG(ctx.Session()->IsSession(), "Session is already a domain");
LOG_DEBUG(Service, "called, server_session={}", ctx.Session()->GetObjectId());
ctx.Session()->ConvertToDomain();
IPC::ResponseBuilder rb{ctx, 3};
rb.Push(RESULT_SUCCESS);
rb.Push<u32>(1); // Converted sessions start with 1 request handler
LOG_DEBUG(Service, "called, server_session={}", ctx.Session()->GetObjectId());
}
void Controller::DuplicateSession(Kernel::HLERequestContext& ctx) {
// TODO(bunnei): This is just creating a new handle to the same Session. I assume this is wrong
// and that we probably want to actually make an entirely new Session, but we still need to
// verify this on hardware.
LOG_DEBUG(Service, "called");
IPC::ResponseBuilder rb{ctx, 2, 0, 1, IPC::ResponseBuilder::Flags::AlwaysMoveHandles};
rb.Push(RESULT_SUCCESS);
Kernel::SharedPtr<Kernel::ClientSession> session{ctx.Session()->parent->client};
rb.PushMoveObjects(session);
LOG_DEBUG(Service, "called, session={}", session->GetObjectId());
LOG_DEBUG(Service, "session={}", session->GetObjectId());
}
void Controller::DuplicateSessionEx(Kernel::HLERequestContext& ctx) {
@@ -42,11 +43,11 @@ void Controller::DuplicateSessionEx(Kernel::HLERequestContext& ctx) {
}
void Controller::QueryPointerBufferSize(Kernel::HLERequestContext& ctx) {
LOG_WARNING(Service, "(STUBBED) called");
IPC::ResponseBuilder rb{ctx, 3};
rb.Push(RESULT_SUCCESS);
rb.Push<u16>(0x500);
LOG_WARNING(Service, "(STUBBED) called");
}
Controller::Controller() : ServiceFramework("IpcController") {

View File

@@ -63,7 +63,7 @@ ResultVal<Kernel::SharedPtr<Kernel::ServerPort>> ServiceManager::RegisterService
return MakeResult<Kernel::SharedPtr<Kernel::ServerPort>>(std::move(server_port));
}
ResultCode ServiceManager::UnregisterService(std::string name) {
ResultCode ServiceManager::UnregisterService(const std::string& name) {
CASCADE_CODE(ValidateServiceName(name));
const auto iter = registered_services.find(name);
@@ -103,9 +103,10 @@ SM::~SM() = default;
* 0: ResultCode
*/
void SM::Initialize(Kernel::HLERequestContext& ctx) {
LOG_DEBUG(Service_SM, "called");
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS);
LOG_DEBUG(Service_SM, "called");
}
void SM::GetService(Kernel::HLERequestContext& ctx) {
@@ -172,6 +173,7 @@ void SM::UnregisterService(Kernel::HLERequestContext& ctx) {
const auto end = std::find(name_buf.begin(), name_buf.end(), '\0');
const std::string name(name_buf.begin(), end);
LOG_DEBUG(Service_SM, "called with name={}", name);
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(service_manager->UnregisterService(name));

View File

@@ -50,7 +50,7 @@ public:
ResultVal<Kernel::SharedPtr<Kernel::ServerPort>> RegisterService(std::string name,
unsigned int max_sessions);
ResultCode UnregisterService(std::string name);
ResultCode UnregisterService(const std::string& name);
ResultVal<Kernel::SharedPtr<Kernel::ClientPort>> GetServicePort(const std::string& name);
ResultVal<Kernel::SharedPtr<Kernel::ClientSession>> ConnectToService(const std::string& name);

View File

@@ -24,6 +24,8 @@ Module::Interface::Interface(std::shared_ptr<Module> module, const char* name)
Module::Interface::~Interface() = default;
void Module::Interface::GetRandomBytes(Kernel::HLERequestContext& ctx) {
LOG_DEBUG(Service_SPL, "called");
IPC::RequestParser rp{ctx};
std::size_t size = ctx.GetWriteBufferSize();
@@ -36,7 +38,6 @@ void Module::Interface::GetRandomBytes(Kernel::HLERequestContext& ctx) {
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS);
LOG_DEBUG(Service_SPL, "called");
}
void InstallInterfaces(SM::ServiceManager& service_manager) {

View File

@@ -69,6 +69,7 @@ public:
private:
void SetOption(Kernel::HLERequestContext& ctx) {
LOG_WARNING(Service_SSL, "(STUBBED) called");
IPC::RequestParser rp{ctx};
IPC::ResponseBuilder rb{ctx, 2};
@@ -114,6 +115,7 @@ private:
void SetInterfaceVersion(Kernel::HLERequestContext& ctx) {
LOG_DEBUG(Service_SSL, "called");
IPC::RequestParser rp{ctx};
ssl_version = rp.Pop<u32>();

View File

@@ -72,6 +72,7 @@ private:
std::chrono::system_clock::now().time_since_epoch())
.count()};
LOG_DEBUG(Service_Time, "called");
IPC::ResponseBuilder rb{ctx, 4};
rb.Push(RESULT_SUCCESS);
rb.Push<u64>(time_since_epoch);
@@ -79,6 +80,7 @@ private:
void GetSystemClockContext(Kernel::HLERequestContext& ctx) {
LOG_WARNING(Service_Time, "(STUBBED) called");
SystemClockContext system_clock_ontext{};
IPC::ResponseBuilder rb{ctx, (sizeof(SystemClockContext) / 4) + 2};
rb.Push(RESULT_SUCCESS);
@@ -98,6 +100,7 @@ public:
private:
void GetCurrentTimePoint(Kernel::HLERequestContext& ctx) {
LOG_DEBUG(Service_Time, "called");
SteadyClockTimePoint steady_clock_time_point{
CoreTiming::cyclesToMs(CoreTiming::GetTicks()) / 1000};
IPC::ResponseBuilder rb{ctx, (sizeof(SteadyClockTimePoint) / 4) + 2};
@@ -130,6 +133,7 @@ private:
void GetDeviceLocationName(Kernel::HLERequestContext& ctx) {
LOG_DEBUG(Service_Time, "called");
IPC::ResponseBuilder rb{ctx, (sizeof(LocationName) / 4) + 2};
rb.Push(RESULT_SUCCESS);
rb.PushRaw(location_name);
@@ -137,6 +141,7 @@ private:
void GetTotalLocationNameCount(Kernel::HLERequestContext& ctx) {
LOG_WARNING(Service_Time, "(STUBBED) called");
IPC::ResponseBuilder rb{ctx, 3};
rb.Push(RESULT_SUCCESS);
rb.Push<u32>(0);
@@ -154,7 +159,6 @@ private:
void ToCalendarTime(Kernel::HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
const u64 posix_time = rp.Pop<u64>();
LOG_WARNING(Service_Time, "(STUBBED) called, posix_time=0x{:016X}", posix_time);
TimeZoneRule time_zone_rule{};
@@ -175,7 +179,6 @@ private:
void ToCalendarTimeWithMyRule(Kernel::HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
const u64 posix_time = rp.Pop<u64>();
LOG_WARNING(Service_Time, "(STUBBED) called, posix_time=0x{:016X}", posix_time);
CalendarTime calendar_time{2018, 1, 1, 0, 0, 0};
@@ -192,6 +195,7 @@ private:
void ToPosixTime(Kernel::HLERequestContext& ctx) {
// TODO(ogniK): Figure out how to handle multiple times
LOG_WARNING(Service_Time, "(STUBBED) called");
IPC::RequestParser rp{ctx};
auto calendar_time = rp.PopRaw<CalendarTime>();
auto posix_time = CalendarToPosix(calendar_time, {});
@@ -204,6 +208,7 @@ private:
void ToPosixTimeWithMyRule(Kernel::HLERequestContext& ctx) {
LOG_WARNING(Service_Time, "(STUBBED) called");
IPC::RequestParser rp{ctx};
auto calendar_time = rp.PopRaw<CalendarTime>();
auto posix_time = CalendarToPosix(calendar_time, {});
@@ -216,38 +221,43 @@ private:
};
void Module::Interface::GetStandardUserSystemClock(Kernel::HLERequestContext& ctx) {
LOG_DEBUG(Service_Time, "called");
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(RESULT_SUCCESS);
rb.PushIpcInterface<ISystemClock>();
LOG_DEBUG(Service_Time, "called");
}
void Module::Interface::GetStandardNetworkSystemClock(Kernel::HLERequestContext& ctx) {
LOG_DEBUG(Service_Time, "called");
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(RESULT_SUCCESS);
rb.PushIpcInterface<ISystemClock>();
LOG_DEBUG(Service_Time, "called");
}
void Module::Interface::GetStandardSteadyClock(Kernel::HLERequestContext& ctx) {
LOG_DEBUG(Service_Time, "called");
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(RESULT_SUCCESS);
rb.PushIpcInterface<ISteadyClock>();
LOG_DEBUG(Service_Time, "called");
}
void Module::Interface::GetTimeZoneService(Kernel::HLERequestContext& ctx) {
LOG_DEBUG(Service_Time, "called");
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(RESULT_SUCCESS);
rb.PushIpcInterface<ITimeZoneService>();
LOG_DEBUG(Service_Time, "called");
}
void Module::Interface::GetStandardLocalSystemClock(Kernel::HLERequestContext& ctx) {
LOG_DEBUG(Service_Time, "called");
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(RESULT_SUCCESS);
rb.PushIpcInterface<ISystemClock>();
LOG_DEBUG(Service_Time, "called");
}
void Module::Interface::GetClockSnapshot(Kernel::HLERequestContext& ctx) {
@@ -265,6 +275,7 @@ void Module::Interface::GetClockSnapshot(Kernel::HLERequestContext& ctx) {
const std::time_t time(time_since_epoch);
const std::tm* tm = std::localtime(&time);
if (tm == nullptr) {
LOG_ERROR(Service_Time, "tm is a nullptr");
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(ResultCode(-1)); // TODO(ogniK): Find appropriate error code
return;

View File

@@ -73,7 +73,7 @@ public:
{3, nullptr, "Populate"},
{4, nullptr, "PostBufferAsync"},
{5, nullptr, "GetXferReport"},
{6, nullptr, "Unknown2"},
{6, nullptr, "PostBufferMultiAsync"},
{7, nullptr, "Unknown3"},
{8, nullptr, "Unknown4"},
};
@@ -159,11 +159,11 @@ public:
private:
void GetPdSession(Kernel::HLERequestContext& ctx) {
LOG_DEBUG(Service_USB, "called");
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(RESULT_SUCCESS);
rb.PushIpcInterface<IPdSession>();
LOG_DEBUG(Service_USB, "called");
}
};

View File

@@ -18,7 +18,8 @@
#include "common/swap.h"
#include "core/core_timing.h"
#include "core/hle/ipc_helpers.h"
#include "core/hle/kernel/event.h"
#include "core/hle/kernel/readable_event.h"
#include "core/hle/kernel/writable_event.h"
#include "core/hle/service/nvdrv/nvdrv.h"
#include "core/hle/service/nvflinger/buffer_queue.h"
#include "core/hle/service/nvflinger/nvflinger.h"
@@ -504,10 +505,10 @@ private:
u32 id = rp.Pop<u32>();
auto transaction = static_cast<TransactionId>(rp.Pop<u32>());
u32 flags = rp.Pop<u32>();
auto buffer_queue = nv_flinger->GetBufferQueue(id);
LOG_DEBUG(Service_VI, "called, transaction={:X}", static_cast<u32>(transaction));
auto buffer_queue = nv_flinger->GetBufferQueue(id);
if (transaction == TransactionId::Connect) {
IGBPConnectRequestParcel request{ctx.ReadBuffer()};
IGBPConnectResponseParcel response{
@@ -542,12 +543,14 @@ private:
// Repeat TransactParcel DequeueBuffer when a buffer is available
auto buffer_queue = nv_flinger->GetBufferQueue(id);
std::optional<u32> slot = buffer_queue->DequeueBuffer(width, height);
ASSERT_MSG(slot != std::nullopt, "Could not dequeue buffer.");
IGBPDequeueBufferResponseParcel response{*slot};
ctx.WriteBuffer(response.Serialize());
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS);
},
buffer_queue->GetBufferWaitEvent());
buffer_queue->GetWritableBufferWaitEvent());
}
} else if (transaction == TransactionId::RequestBuffer) {
IGBPRequestBufferRequestParcel request{ctx.ReadBuffer()};
@@ -593,9 +596,9 @@ private:
u32 id = rp.Pop<u32>();
s32 addval = rp.PopRaw<s32>();
u32 type = rp.Pop<u32>();
LOG_WARNING(Service_VI, "(STUBBED) called id={}, addval={:08X}, type={:08X}", id, addval,
type);
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS);
}
@@ -604,12 +607,11 @@ private:
IPC::RequestParser rp{ctx};
u32 id = rp.Pop<u32>();
u32 unknown = rp.Pop<u32>();
LOG_WARNING(Service_VI, "(STUBBED) called id={}, unknown={:08X}", id, unknown);
auto buffer_queue = nv_flinger->GetBufferQueue(id);
// TODO(Subv): Find out what this actually is.
LOG_WARNING(Service_VI, "(STUBBED) called id={}, unknown={:08X}", id, unknown);
IPC::ResponseBuilder rb{ctx, 2, 1};
rb.Push(RESULT_SUCCESS);
rb.PushCopyObjects(buffer_queue->GetBufferWaitEvent());
@@ -673,6 +675,7 @@ public:
private:
void SetLayerZ(Kernel::HLERequestContext& ctx) {
LOG_WARNING(Service_VI, "(STUBBED) called");
IPC::RequestParser rp{ctx};
u64 layer_id = rp.Pop<u64>();
u64 z_value = rp.Pop<u64>();
@@ -685,13 +688,16 @@ private:
IPC::RequestParser rp{ctx};
u64 layer_id = rp.Pop<u64>();
bool visibility = rp.Pop<bool>();
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS);
LOG_WARNING(Service_VI, "(STUBBED) called, layer_id=0x{:08X}, visibility={}", layer_id,
visibility);
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS);
}
void GetDisplayMode(Kernel::HLERequestContext& ctx) {
LOG_WARNING(Service_VI, "(STUBBED) called");
IPC::ResponseBuilder rb{ctx, 6};
rb.Push(RESULT_SUCCESS);
@@ -707,10 +713,8 @@ private:
static_cast<u32>(Settings::values.resolution_factor));
}
rb.PushRaw<float>(60.0f);
rb.PushRaw<float>(60.0f); // This wouldn't seem to be correct for 30 fps games.
rb.Push<u32>(0);
LOG_DEBUG(Service_VI, "called");
}
};
@@ -793,6 +797,7 @@ public:
private:
void CloseDisplay(Kernel::HLERequestContext& ctx) {
LOG_WARNING(Service_VI, "(STUBBED) called");
IPC::RequestParser rp{ctx};
u64 display = rp.Pop<u64>();
@@ -802,6 +807,7 @@ private:
void CreateManagedLayer(Kernel::HLERequestContext& ctx) {
LOG_WARNING(Service_VI, "(STUBBED) called");
IPC::RequestParser rp{ctx};
u32 unknown = rp.Pop<u32>();
rp.Skip(1, false);
@@ -817,6 +823,7 @@ private:
void AddToLayerStack(Kernel::HLERequestContext& ctx) {
LOG_WARNING(Service_VI, "(STUBBED) called");
IPC::RequestParser rp{ctx};
u32 stack = rp.Pop<u32>();
u64 layer_id = rp.Pop<u64>();
@@ -829,10 +836,11 @@ private:
IPC::RequestParser rp{ctx};
u64 layer_id = rp.Pop<u64>();
bool visibility = rp.Pop<bool>();
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS);
LOG_WARNING(Service_VI, "(STUBBED) called, layer_id=0x{:X}, visibility={}", layer_id,
visibility);
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS);
}
std::shared_ptr<NVFlinger::NVFlinger> nv_flinger;
@@ -878,6 +886,7 @@ private:
void OpenDisplay(Kernel::HLERequestContext& ctx) {
LOG_WARNING(Service_VI, "(STUBBED) called");
IPC::RequestParser rp{ctx};
auto name_buf = rp.PopRaw<std::array<u8, 0x40>>();
auto end = std::find(name_buf.begin(), name_buf.end(), '\0');
@@ -893,6 +902,7 @@ private:
void CloseDisplay(Kernel::HLERequestContext& ctx) {
LOG_WARNING(Service_VI, "(STUBBED) called");
IPC::RequestParser rp{ctx};
u64 display_id = rp.Pop<u64>();
@@ -902,6 +912,7 @@ private:
void GetDisplayResolution(Kernel::HLERequestContext& ctx) {
LOG_WARNING(Service_VI, "(STUBBED) called");
IPC::RequestParser rp{ctx};
u64 display_id = rp.Pop<u64>();
@@ -923,6 +934,7 @@ private:
void SetLayerScalingMode(Kernel::HLERequestContext& ctx) {
LOG_WARNING(Service_VI, "(STUBBED) called");
IPC::RequestParser rp{ctx};
u32 scaling_mode = rp.Pop<u32>();
u64 unknown = rp.Pop<u64>();
@@ -932,6 +944,8 @@ private:
}
void ListDisplays(Kernel::HLERequestContext& ctx) {
LOG_WARNING(Service_VI, "(STUBBED) called");
IPC::RequestParser rp{ctx};
DisplayInfo display_info;
display_info.width *= static_cast<u64>(Settings::values.resolution_factor);
@@ -940,11 +954,11 @@ private:
IPC::ResponseBuilder rb{ctx, 4};
rb.Push(RESULT_SUCCESS);
rb.Push<u64>(1);
LOG_WARNING(Service_VI, "(STUBBED) called");
}
void OpenLayer(Kernel::HLERequestContext& ctx) {
LOG_DEBUG(Service_VI, "called");
IPC::RequestParser rp{ctx};
auto name_buf = rp.PopRaw<std::array<u8, 0x40>>();
auto end = std::find(name_buf.begin(), name_buf.end(), '\0');
@@ -995,6 +1009,7 @@ private:
void GetDisplayVsyncEvent(Kernel::HLERequestContext& ctx) {
LOG_WARNING(Service_VI, "(STUBBED) called");
IPC::RequestParser rp{ctx};
u64 display_id = rp.Pop<u64>();

View File

@@ -1,6 +1,6 @@
add_library(video_core STATIC
command_processor.cpp
command_processor.h
dma_pusher.cpp
dma_pusher.h
debug_utils/debug_utils.cpp
debug_utils/debug_utils.h
engines/fermi_2d.cpp
@@ -21,6 +21,8 @@ add_library(video_core STATIC
macro_interpreter.h
memory_manager.cpp
memory_manager.h
morton.cpp
morton.h
rasterizer_cache.cpp
rasterizer_cache.h
rasterizer_interface.h
@@ -62,7 +64,6 @@ add_library(video_core STATIC
textures/decoders.cpp
textures/decoders.h
textures/texture.h
utils.h
video_core.cpp
video_core.h
)

View File

@@ -34,6 +34,9 @@ MICROPROFILE_DEFINE(ProcessCommandLists, "GPU", "Execute command buffer", MP_RGB
void GPU::ProcessCommandLists(const std::vector<CommandListHeader>& commands) {
MICROPROFILE_SCOPE(ProcessCommandLists);
// On entering GPU code, assume all memory may be touched by the ARM core.
maxwell_3d->dirty_flags.OnMemoryWrite();
auto WriteReg = [this](u32 method, u32 subchannel, u32 value, u32 remaining_params) {
LOG_TRACE(HW_GPU,
"Processing method {:08X} on subchannel {} value "

View File

@@ -1,53 +0,0 @@
// Copyright 2018 yuzu Emulator Project
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#pragma once
#include <type_traits>
#include "common/bit_field.h"
#include "common/common_types.h"
#include "video_core/memory_manager.h"
namespace Tegra {
enum class SubmissionMode : u32 {
IncreasingOld = 0,
Increasing = 1,
NonIncreasingOld = 2,
NonIncreasing = 3,
Inline = 4,
IncreaseOnce = 5
};
struct CommandListHeader {
u32 entry0; // gpu_va_lo
union {
u32 entry1; // gpu_va_hi | (unk_0x02 << 0x08) | (size << 0x0A) | (unk_0x01 << 0x1F)
BitField<0, 8, u32> gpu_va_hi;
BitField<8, 2, u32> unk1;
BitField<10, 21, u32> sz;
BitField<31, 1, u32> unk2;
};
GPUVAddr Address() const {
return (static_cast<GPUVAddr>(gpu_va_hi) << 32) | entry0;
}
};
static_assert(sizeof(CommandListHeader) == 8, "CommandListHeader is incorrect size");
union CommandHeader {
u32 hex;
BitField<0, 13, u32> method;
BitField<13, 3, u32> subchannel;
BitField<16, 13, u32> arg_count;
BitField<16, 13, u32> inline_data;
BitField<29, 3, SubmissionMode> mode;
};
static_assert(std::is_standard_layout_v<CommandHeader>, "CommandHeader is not standard layout");
static_assert(sizeof(CommandHeader) == sizeof(u32), "CommandHeader has incorrect size!");
} // namespace Tegra

View File

@@ -0,0 +1,123 @@
// Copyright 2018 yuzu Emulator Project
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#include "common/microprofile.h"
#include "core/core.h"
#include "core/memory.h"
#include "video_core/dma_pusher.h"
#include "video_core/engines/maxwell_3d.h"
#include "video_core/gpu.h"
namespace Tegra {
DmaPusher::DmaPusher(GPU& gpu) : gpu(gpu) {}
DmaPusher::~DmaPusher() = default;
MICROPROFILE_DEFINE(DispatchCalls, "GPU", "Execute command buffer", MP_RGB(128, 128, 192));
void DmaPusher::DispatchCalls() {
MICROPROFILE_SCOPE(DispatchCalls);
// On entering GPU code, assume all memory may be touched by the ARM core.
gpu.Maxwell3D().dirty_flags.OnMemoryWrite();
dma_pushbuffer_subindex = 0;
while (Core::System::GetInstance().IsPoweredOn()) {
if (!Step()) {
break;
}
}
}
bool DmaPusher::Step() {
if (dma_get != dma_put) {
// Push buffer non-empty, read a word
const CommandHeader command_header{
Memory::Read32(*gpu.MemoryManager().GpuToCpuAddress(dma_get))};
dma_get += sizeof(u32);
if (!non_main) {
dma_mget = dma_get;
}
// now, see if we're in the middle of a command
if (dma_state.length_pending) {
// Second word of long non-inc methods command - method count
dma_state.length_pending = 0;
dma_state.method_count = command_header.method_count_;
} else if (dma_state.method_count) {
// Data word of methods command
CallMethod(command_header.argument);
if (!dma_state.non_incrementing) {
dma_state.method++;
}
if (dma_increment_once) {
dma_state.non_incrementing = true;
}
dma_state.method_count--;
} else {
// No command active - this is the first word of a new one
switch (command_header.mode) {
case SubmissionMode::Increasing:
SetState(command_header);
dma_state.non_incrementing = false;
dma_increment_once = false;
break;
case SubmissionMode::NonIncreasing:
SetState(command_header);
dma_state.non_incrementing = true;
dma_increment_once = false;
break;
case SubmissionMode::Inline:
dma_state.method = command_header.method;
dma_state.subchannel = command_header.subchannel;
CallMethod(command_header.arg_count);
dma_state.non_incrementing = true;
dma_increment_once = false;
break;
case SubmissionMode::IncreaseOnce:
SetState(command_header);
dma_state.non_incrementing = false;
dma_increment_once = true;
break;
}
}
} else if (ib_enable && !dma_pushbuffer.empty()) {
// Current pushbuffer empty, but we have more IB entries to read
const CommandList& command_list{dma_pushbuffer.front()};
const CommandListHeader& command_list_header{command_list[dma_pushbuffer_subindex++]};
dma_get = command_list_header.addr;
dma_put = dma_get + command_list_header.size * sizeof(u32);
non_main = command_list_header.is_non_main;
if (dma_pushbuffer_subindex >= command_list.size()) {
// We've gone through the current list, remove it from the queue
dma_pushbuffer.pop();
dma_pushbuffer_subindex = 0;
}
} else {
// Otherwise, pushbuffer empty and IB empty or nonexistent - nothing to do
return {};
}
return true;
}
void DmaPusher::SetState(const CommandHeader& command_header) {
dma_state.method = command_header.method;
dma_state.subchannel = command_header.subchannel;
dma_state.method_count = command_header.method_count;
}
void DmaPusher::CallMethod(u32 argument) const {
gpu.CallMethod({dma_state.method, argument, dma_state.subchannel, dma_state.method_count});
}
} // namespace Tegra

View File

@@ -0,0 +1,99 @@
// Copyright 2018 yuzu Emulator Project
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#pragma once
#include <vector>
#include <queue>
#include "common/bit_field.h"
#include "common/common_types.h"
#include "video_core/memory_manager.h"
namespace Tegra {
enum class SubmissionMode : u32 {
IncreasingOld = 0,
Increasing = 1,
NonIncreasingOld = 2,
NonIncreasing = 3,
Inline = 4,
IncreaseOnce = 5
};
struct CommandListHeader {
union {
u64 raw;
BitField<0, 40, GPUVAddr> addr;
BitField<41, 1, u64> is_non_main;
BitField<42, 21, u64> size;
};
};
static_assert(sizeof(CommandListHeader) == sizeof(u64), "CommandListHeader is incorrect size");
union CommandHeader {
u32 argument;
BitField<0, 13, u32> method;
BitField<0, 24, u32> method_count_;
BitField<13, 3, u32> subchannel;
BitField<16, 13, u32> arg_count;
BitField<16, 13, u32> method_count;
BitField<29, 3, SubmissionMode> mode;
};
static_assert(std::is_standard_layout_v<CommandHeader>, "CommandHeader is not standard layout");
static_assert(sizeof(CommandHeader) == sizeof(u32), "CommandHeader has incorrect size!");
class GPU;
using CommandList = std::vector<Tegra::CommandListHeader>;
/**
* The DmaPusher class implements DMA submission to FIFOs, providing an area of memory that the
* emulated app fills with commands and tells PFIFO to process. The pushbuffers are then assembled
* into a "command stream" consisting of 32-bit words that make up "commands".
* See https://envytools.readthedocs.io/en/latest/hw/fifo/dma-pusher.html#fifo-dma-pusher for
* details on this implementation.
*/
class DmaPusher {
public:
explicit DmaPusher(GPU& gpu);
~DmaPusher();
void Push(CommandList&& entries) {
dma_pushbuffer.push(std::move(entries));
}
void DispatchCalls();
private:
bool Step();
void SetState(const CommandHeader& command_header);
void CallMethod(u32 argument) const;
GPU& gpu;
std::queue<CommandList> dma_pushbuffer; ///< Queue of command lists to be processed
std::size_t dma_pushbuffer_subindex{}; ///< Index within a command list within the pushbuffer
struct DmaState {
u32 method; ///< Current method
u32 subchannel; ///< Current subchannel
u32 method_count; ///< Current method count
u32 length_pending; ///< Large NI command length pending
bool non_incrementing; ///< Current commands NI flag
};
DmaState dma_state{};
bool dma_increment_once{};
GPUVAddr dma_put{}; ///< pushbuffer current end address
GPUVAddr dma_get{}; ///< pushbuffer current read address
GPUVAddr dma_mget{}; ///< main pushbuffer last read address
bool ib_enable{true}; ///< IB mode enabled
bool non_main{}; ///< non-main pushbuffer active
};
} // namespace Tegra

View File

@@ -2,8 +2,10 @@
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#include "core/core.h"
#include "core/memory.h"
#include "video_core/engines/fermi_2d.h"
#include "video_core/engines/maxwell_3d.h"
#include "video_core/rasterizer_interface.h"
#include "video_core/textures/decoders.h"
@@ -12,13 +14,13 @@ namespace Tegra::Engines {
Fermi2D::Fermi2D(VideoCore::RasterizerInterface& rasterizer, MemoryManager& memory_manager)
: memory_manager(memory_manager), rasterizer{rasterizer} {}
void Fermi2D::WriteReg(u32 method, u32 value) {
ASSERT_MSG(method < Regs::NUM_REGS,
void Fermi2D::CallMethod(const GPU::MethodCall& method_call) {
ASSERT_MSG(method_call.method < Regs::NUM_REGS,
"Invalid Fermi2D register, increase the size of the Regs structure");
regs.reg_array[method] = value;
regs.reg_array[method_call.method] = method_call.argument;
switch (method) {
switch (method_call.method) {
case FERMI2D_REG_INDEX(trigger): {
HandleSurfaceCopy();
break;
@@ -47,6 +49,9 @@ void Fermi2D::HandleSurfaceCopy() {
u32 dst_bytes_per_pixel = RenderTargetBytesPerPixel(regs.dst.format);
if (!rasterizer.AccelerateSurfaceCopy(regs.src, regs.dst)) {
// All copies here update the main memory, so mark all rasterizer states as invalid.
Core::System::GetInstance().GPU().Maxwell3D().dirty_flags.OnMemoryWrite();
rasterizer.FlushRegion(source_cpu, src_bytes_per_pixel * regs.src.width * regs.src.height);
// We have to invalidate the destination region to evict any outdated surfaces from the
// cache. We do this before actually writing the new data because the destination address
@@ -68,13 +73,13 @@ void Fermi2D::HandleSurfaceCopy() {
Texture::CopySwizzledData(regs.src.width, regs.src.height, regs.src.depth,
src_bytes_per_pixel, dst_bytes_per_pixel, src_buffer,
dst_buffer, true, regs.src.BlockHeight(),
regs.src.BlockDepth());
regs.src.BlockDepth(), 0);
} else {
// If the input is linear and the output is tiled, swizzle the input and copy it over.
Texture::CopySwizzledData(regs.src.width, regs.src.height, regs.src.depth,
src_bytes_per_pixel, dst_bytes_per_pixel, dst_buffer,
src_buffer, false, regs.dst.BlockHeight(),
regs.dst.BlockDepth());
regs.dst.BlockDepth(), 0);
}
}
}

View File

@@ -27,7 +27,7 @@ public:
~Fermi2D() = default;
/// Write the value to the register identified by method.
void WriteReg(u32 method, u32 value);
void CallMethod(const GPU::MethodCall& method_call);
struct Regs {
static constexpr std::size_t NUM_REGS = 0x258;

View File

@@ -3,8 +3,10 @@
// Refer to the license.txt file included.
#include "common/logging/log.h"
#include "core/core.h"
#include "core/memory.h"
#include "video_core/engines/kepler_memory.h"
#include "video_core/engines/maxwell_3d.h"
#include "video_core/rasterizer_interface.h"
namespace Tegra::Engines {
@@ -15,19 +17,19 @@ KeplerMemory::KeplerMemory(VideoCore::RasterizerInterface& rasterizer,
KeplerMemory::~KeplerMemory() = default;
void KeplerMemory::WriteReg(u32 method, u32 value) {
ASSERT_MSG(method < Regs::NUM_REGS,
void KeplerMemory::CallMethod(const GPU::MethodCall& method_call) {
ASSERT_MSG(method_call.method < Regs::NUM_REGS,
"Invalid KeplerMemory register, increase the size of the Regs structure");
regs.reg_array[method] = value;
regs.reg_array[method_call.method] = method_call.argument;
switch (method) {
switch (method_call.method) {
case KEPLERMEMORY_REG_INDEX(exec): {
state.write_offset = 0;
break;
}
case KEPLERMEMORY_REG_INDEX(data): {
ProcessData(value);
ProcessData(method_call.argument);
break;
}
}
@@ -47,6 +49,7 @@ void KeplerMemory::ProcessData(u32 data) {
rasterizer.InvalidateRegion(dest_address, sizeof(u32));
Memory::Write32(dest_address, data);
Core::System::GetInstance().GPU().Maxwell3D().dirty_flags.OnMemoryWrite();
state.write_offset++;
}

View File

@@ -9,6 +9,7 @@
#include "common/bit_field.h"
#include "common/common_funcs.h"
#include "common/common_types.h"
#include "video_core/gpu.h"
#include "video_core/memory_manager.h"
namespace VideoCore {
@@ -26,7 +27,7 @@ public:
~KeplerMemory();
/// Write the value to the register identified by method.
void WriteReg(u32 method, u32 value);
void CallMethod(const GPU::MethodCall& method_call);
struct Regs {
static constexpr size_t NUM_REGS = 0x7F;

View File

@@ -97,57 +97,74 @@ void Maxwell3D::CallMacroMethod(u32 method, std::vector<u32> parameters) {
macro_interpreter.Execute(search->second, std::move(parameters));
}
void Maxwell3D::WriteReg(u32 method, u32 value, u32 remaining_params) {
void Maxwell3D::CallMethod(const GPU::MethodCall& method_call) {
auto debug_context = Core::System::GetInstance().GetGPUDebugContext();
// It is an error to write to a register other than the current macro's ARG register before it
// has finished execution.
if (executing_macro != 0) {
ASSERT(method == executing_macro + 1);
ASSERT(method_call.method == executing_macro + 1);
}
// Methods after 0xE00 are special, they're actually triggers for some microcode that was
// uploaded to the GPU during initialization.
if (method >= MacroRegistersStart) {
if (method_call.method >= MacroRegistersStart) {
// We're trying to execute a macro
if (executing_macro == 0) {
// A macro call must begin by writing the macro method's register, not its argument.
ASSERT_MSG((method % 2) == 0,
ASSERT_MSG((method_call.method % 2) == 0,
"Can't start macro execution by writing to the ARGS register");
executing_macro = method;
executing_macro = method_call.method;
}
macro_params.push_back(value);
macro_params.push_back(method_call.argument);
// Call the macro when there are no more parameters in the command buffer
if (remaining_params == 0) {
if (method_call.IsLastCall()) {
CallMacroMethod(executing_macro, std::move(macro_params));
}
return;
}
ASSERT_MSG(method < Regs::NUM_REGS,
ASSERT_MSG(method_call.method < Regs::NUM_REGS,
"Invalid Maxwell3D register, increase the size of the Regs structure");
if (debug_context) {
debug_context->OnEvent(Tegra::DebugContext::Event::MaxwellCommandLoaded, nullptr);
}
if (regs.reg_array[method] != value) {
regs.reg_array[method] = value;
if (method >= MAXWELL3D_REG_INDEX(vertex_attrib_format) &&
method < MAXWELL3D_REG_INDEX(vertex_attrib_format) + regs.vertex_attrib_format.size()) {
if (regs.reg_array[method_call.method] != method_call.argument) {
regs.reg_array[method_call.method] = method_call.argument;
// Vertex format
if (method_call.method >= MAXWELL3D_REG_INDEX(vertex_attrib_format) &&
method_call.method <
MAXWELL3D_REG_INDEX(vertex_attrib_format) + regs.vertex_attrib_format.size()) {
dirty_flags.vertex_attrib_format = true;
}
// Vertex buffer
if (method_call.method >= MAXWELL3D_REG_INDEX(vertex_array) &&
method_call.method < MAXWELL3D_REG_INDEX(vertex_array) + 4 * 32) {
dirty_flags.vertex_array |=
1u << ((method_call.method - MAXWELL3D_REG_INDEX(vertex_array)) >> 2);
} else if (method_call.method >= MAXWELL3D_REG_INDEX(vertex_array_limit) &&
method_call.method < MAXWELL3D_REG_INDEX(vertex_array_limit) + 2 * 32) {
dirty_flags.vertex_array |=
1u << ((method_call.method - MAXWELL3D_REG_INDEX(vertex_array_limit)) >> 1);
} else if (method_call.method >= MAXWELL3D_REG_INDEX(instanced_arrays) &&
method_call.method < MAXWELL3D_REG_INDEX(instanced_arrays) + 32) {
dirty_flags.vertex_array |=
1u << (method_call.method - MAXWELL3D_REG_INDEX(instanced_arrays));
}
}
switch (method) {
switch (method_call.method) {
case MAXWELL3D_REG_INDEX(macros.data): {
ProcessMacroUpload(value);
ProcessMacroUpload(method_call.argument);
break;
}
case MAXWELL3D_REG_INDEX(macros.bind): {
ProcessMacroBind(value);
ProcessMacroBind(method_call.argument);
break;
}
case MAXWELL3D_REG_INDEX(const_buffer.cb_data[0]):
@@ -166,7 +183,7 @@ void Maxwell3D::WriteReg(u32 method, u32 value, u32 remaining_params) {
case MAXWELL3D_REG_INDEX(const_buffer.cb_data[13]):
case MAXWELL3D_REG_INDEX(const_buffer.cb_data[14]):
case MAXWELL3D_REG_INDEX(const_buffer.cb_data[15]): {
ProcessCBData(value);
ProcessCBData(method_call.argument);
break;
}
case MAXWELL3D_REG_INDEX(cb_bind[0].raw_config): {
@@ -270,6 +287,7 @@ void Maxwell3D::ProcessQueryGet() {
query_result.timestamp = CoreTiming::GetTicks();
Memory::WriteBlock(*address, &query_result, sizeof(query_result));
}
dirty_flags.OnMemoryWrite();
break;
}
default:
@@ -346,6 +364,7 @@ void Maxwell3D::ProcessCBData(u32 value) {
memory_manager.GpuToCpuAddress(buffer_address + regs.const_buffer.cb_pos);
Memory::Write32(*address, value);
dirty_flags.OnMemoryWrite();
// Increment the current buffer position.
regs.const_buffer.cb_pos = regs.const_buffer.cb_pos + 4;

View File

@@ -42,6 +42,7 @@ public:
static constexpr std::size_t NumVertexArrays = 32;
static constexpr std::size_t NumVertexAttributes = 32;
static constexpr std::size_t NumTextureSamplers = 32;
static constexpr std::size_t NumClipDistances = 8;
static constexpr std::size_t MaxShaderProgram = 6;
static constexpr std::size_t MaxShaderStage = 5;
// Maximum number of const buffers per shader stage.
@@ -590,10 +591,18 @@ public:
float clear_color[4];
float clear_depth;
INSERT_PADDING_WORDS(0x3);
s32 clear_stencil;
INSERT_PADDING_WORDS(0x17);
INSERT_PADDING_WORDS(0x7);
u32 polygon_offset_point_enable;
u32 polygon_offset_line_enable;
u32 polygon_offset_fill_enable;
INSERT_PADDING_WORDS(0xD);
std::array<ScissorTest, NumViewports> scissor_test;
@@ -728,6 +737,7 @@ public:
u32 frag_color_clamp;
union {
BitField<0, 1, u32> y_negate;
BitField<4, 1, u32> triangle_rast_flip;
} screen_y_control;
@@ -735,7 +745,20 @@ public:
u32 vb_element_base;
INSERT_PADDING_WORDS(0x38);
INSERT_PADDING_WORDS(0x36);
union {
BitField<0, 1, u32> c0;
BitField<1, 1, u32> c1;
BitField<2, 1, u32> c2;
BitField<3, 1, u32> c3;
BitField<4, 1, u32> c4;
BitField<5, 1, u32> c5;
BitField<6, 1, u32> c6;
BitField<7, 1, u32> c7;
} clip_distance_enabled;
INSERT_PADDING_WORDS(0x1);
float point_size;
@@ -761,7 +784,11 @@ public:
}
} tsc;
INSERT_PADDING_WORDS(0x3);
INSERT_PADDING_WORDS(0x1);
float polygon_offset_factor;
INSERT_PADDING_WORDS(0x1);
struct {
u32 tic_address_high;
@@ -786,7 +813,9 @@ public:
u32 framebuffer_srgb;
INSERT_PADDING_WORDS(0x12);
float polygon_offset_units;
INSERT_PADDING_WORDS(0x11);
union {
BitField<2, 1, u32> coord_origin;
@@ -863,7 +892,9 @@ public:
INSERT_PADDING_WORDS(0x7);
INSERT_PADDING_WORDS(0x20);
INSERT_PADDING_WORDS(0x1F);
float polygon_offset_clamp;
struct {
u32 is_instanced[NumVertexArrays];
@@ -879,8 +910,21 @@ public:
Cull cull;
INSERT_PADDING_WORDS(0x28);
u32 pixel_center_integer;
INSERT_PADDING_WORDS(0x1);
u32 viewport_transform_enabled;
INSERT_PADDING_WORDS(0x3);
union {
BitField<0, 1, u32> depth_range_0_1;
BitField<3, 1, u32> depth_clamp_near;
BitField<4, 1, u32> depth_clamp_far;
} view_volume_clip_control;
INSERT_PADDING_WORDS(0x21);
struct {
u32 enable;
LogicOperation operation;
@@ -1044,6 +1088,11 @@ public:
struct DirtyFlags {
bool vertex_attrib_format = true;
u32 vertex_array = 0xFFFFFFFF;
void OnMemoryWrite() {
vertex_array = 0xFFFFFFFF;
}
};
DirtyFlags dirty_flags;
@@ -1052,7 +1101,7 @@ public:
u32 GetRegisterValue(u32 method) const;
/// Write the value to the register identified by method.
void WriteReg(u32 method, u32 value, u32 remaining_params);
void CallMethod(const GPU::MethodCall& method_call);
/// Returns a list of enabled textures for the specified shader stage.
std::vector<Texture::FullTextureInfo> GetStageTextures(Regs::ShaderStage stage) const;
@@ -1136,6 +1185,9 @@ ASSERT_REG_POSITION(vertex_buffer, 0x35D);
ASSERT_REG_POSITION(clear_color[0], 0x360);
ASSERT_REG_POSITION(clear_depth, 0x364);
ASSERT_REG_POSITION(clear_stencil, 0x368);
ASSERT_REG_POSITION(polygon_offset_point_enable, 0x370);
ASSERT_REG_POSITION(polygon_offset_line_enable, 0x371);
ASSERT_REG_POSITION(polygon_offset_fill_enable, 0x372);
ASSERT_REG_POSITION(scissor_test, 0x380);
ASSERT_REG_POSITION(stencil_back_func_ref, 0x3D5);
ASSERT_REG_POSITION(stencil_back_mask, 0x3D6);
@@ -1170,10 +1222,12 @@ ASSERT_REG_POSITION(stencil_front_mask, 0x4E7);
ASSERT_REG_POSITION(frag_color_clamp, 0x4EA);
ASSERT_REG_POSITION(screen_y_control, 0x4EB);
ASSERT_REG_POSITION(vb_element_base, 0x50D);
ASSERT_REG_POSITION(clip_distance_enabled, 0x544);
ASSERT_REG_POSITION(point_size, 0x546);
ASSERT_REG_POSITION(zeta_enable, 0x54E);
ASSERT_REG_POSITION(multisample_control, 0x54F);
ASSERT_REG_POSITION(tsc, 0x557);
ASSERT_REG_POSITION(polygon_offset_factor, 0x55b);
ASSERT_REG_POSITION(tic, 0x55D);
ASSERT_REG_POSITION(stencil_two_side_enable, 0x565);
ASSERT_REG_POSITION(stencil_back_op_fail, 0x566);
@@ -1181,13 +1235,18 @@ ASSERT_REG_POSITION(stencil_back_op_zfail, 0x567);
ASSERT_REG_POSITION(stencil_back_op_zpass, 0x568);
ASSERT_REG_POSITION(stencil_back_func_func, 0x569);
ASSERT_REG_POSITION(framebuffer_srgb, 0x56E);
ASSERT_REG_POSITION(polygon_offset_units, 0x56F);
ASSERT_REG_POSITION(point_coord_replace, 0x581);
ASSERT_REG_POSITION(code_address, 0x582);
ASSERT_REG_POSITION(draw, 0x585);
ASSERT_REG_POSITION(primitive_restart, 0x591);
ASSERT_REG_POSITION(index_array, 0x5F2);
ASSERT_REG_POSITION(polygon_offset_clamp, 0x61F);
ASSERT_REG_POSITION(instanced_arrays, 0x620);
ASSERT_REG_POSITION(cull, 0x646);
ASSERT_REG_POSITION(pixel_center_integer, 0x649);
ASSERT_REG_POSITION(viewport_transform_enabled, 0x64B);
ASSERT_REG_POSITION(view_volume_clip_control, 0x64F);
ASSERT_REG_POSITION(logic_op, 0x671);
ASSERT_REG_POSITION(clear_buffers, 0x674);
ASSERT_REG_POSITION(color_mask, 0x680);

View File

@@ -8,13 +8,13 @@
namespace Tegra::Engines {
void MaxwellCompute::WriteReg(u32 method, u32 value) {
ASSERT_MSG(method < Regs::NUM_REGS,
void MaxwellCompute::CallMethod(const GPU::MethodCall& method_call) {
ASSERT_MSG(method_call.method < Regs::NUM_REGS,
"Invalid MaxwellCompute register, increase the size of the Regs structure");
regs.reg_array[method] = value;
regs.reg_array[method_call.method] = method_call.argument;
switch (method) {
switch (method_call.method) {
case MAXWELL_COMPUTE_REG_INDEX(compute): {
LOG_CRITICAL(HW_GPU, "Compute shaders are not implemented");
UNREACHABLE();

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