Compare commits

..

123 Commits

Author SHA1 Message Date
Lioncash
ca96dc4676 service: Update service function tables
Updates function tables based off information from SwitchBrew.
2019-04-11 02:47:00 -04:00
bunnei
2598433f9c Merge pull request #2354 from lioncash/header
video_core/texures/texture: Remove unnecessary includes
2019-04-09 19:19:41 -04:00
bunnei
61f63bb994 Merge pull request #1957 from DarkLordZach/title-provider
file_sys: Provide generic interface for accessing game data
2019-04-09 19:16:37 -04:00
bunnei
353a099481 Merge pull request #2366 from FernandoS27/xmad-fix
Correct XMAD mode, psl and high_b on different encodings.
2019-04-09 19:15:01 -04:00
bunnei
1a3098f11a Merge pull request #2132 from FearlessTobi/port-4437
Port citra-emu/citra#4437: "citra-qt: Make hotkeys configurable via the GUI (Attempt 2)"
2019-04-09 18:08:30 -04:00
bunnei
71182643f7 Merge pull request #2370 from lioncash/qt-warn
yuzu/loading_screen: Resolve runtime Qt string formatting warnings
2019-04-09 17:21:18 -04:00
bunnei
bc7e149835 Merge pull request #2369 from FernandoS27/mip-align
gl_backend: Align Pixel Storage
2019-04-09 17:20:43 -04:00
bunnei
088c7c1bb5 Merge pull request #2368 from FernandoS27/fix-lop
Correct LOP_IMM encoding
2019-04-09 17:19:56 -04:00
Hexagon12
b81260c65c Merge pull request #2371 from lioncash/pagetable
kernel/process: Set page table when page table resizes occur.
2019-04-09 20:13:37 +03:00
Lioncash
2abf979c35 kernel/process: Set page table when page table resizes occur.
We need to ensure dynarmic gets a valid pointer if the page table is
resized (the relevant pointers would be invalidated in this scenario).

In this scenario, the page table can be resized depending on what kind
of address space is specified within the NPDM metadata (if it's
present).
2019-04-09 13:00:56 -04:00
Lioncash
b73e433dff yuzu/loading_screen: Resolve runtime Qt string formatting warnings
In our error console, when loading a game, the strings:

QString::arg: Argument missing: "Loading...", 0
QString::arg: Argument missing: "Launching...", 0

would occasionally pop up when the loading screen was running. This was
due to the strings being assumed to have formatting indicators in them,
however only two out of the four strings actually have them.

This only applies the arguments to the strings that have formatting
specifiers provided, which avoids these warnings from occurring.
2019-04-09 10:49:38 -04:00
Fernando Sahmkow
9f16833097 gl_backend: Align Pixel Storage
This commit makes sure GL reads on the correct pack size for the
respective texture buffer.
2019-04-08 17:16:02 -04:00
Fernando Sahmkow
5c55ae4e18 Correct LOP_IMN encoding 2019-04-08 13:39:12 -04:00
Fernando Sahmkow
16adc735a5 Correct XMAD mode, psl and high_b on different encodings. 2019-04-08 13:01:17 -04:00
bunnei
f14328bf0a Merge pull request #2300 from FernandoS27/null-shader
shader_cache: Permit a Null Shader in case of a bad host_ptr.
2019-04-07 17:58:27 -04:00
bunnei
c2fee0e519 Merge pull request #2355 from ReinUsesLisp/sync-point
maxwell_3d: Reduce severity of ProcessSyncPoint
2019-04-07 17:56:11 -04:00
bunnei
06ece52cfe Merge pull request #2359 from FearlessTobi/port-2-prs
Port citra-emu/citra#4718: "fix clang-format target when using a path with spaces on windows"
2019-04-07 17:54:57 -04:00
bunnei
8aaf418bd6 Merge pull request #2306 from ReinUsesLisp/aoffi
shader_ir: Implement AOFFI for TEX and TLD4
2019-04-07 17:52:30 -04:00
bunnei
3c1ce290d0 Merge pull request #2361 from lioncash/pagetable
core/memory: Minor simplifications to page table management
2019-04-07 17:50:31 -04:00
bunnei
6b18a1592f Merge pull request #2321 from ReinUsesLisp/gl-state-rework
gl_state: Rework to enable individual applies
2019-04-07 17:50:07 -04:00
bunnei
21a4e7deea Merge pull request #2098 from FreddyFunk/disk-cache-zstd
gl_shader_disk_cache: Use Zstandard for compression
2019-04-07 17:48:33 -04:00
bunnei
52ad5fa0e8 Merge pull request #2356 from lioncash/pair
kernel/{server_port, server_session}: Return pairs instead of tuples from pair creation functions
2019-04-07 17:48:00 -04:00
bunnei
d9b1c24f4f Merge pull request #2362 from lioncash/enum
core/memory: Remove unused enum constants
2019-04-07 17:46:09 -04:00
bunnei
80162888e6 Merge pull request #2352 from bunnei/mem-manager-fixes
memory_manager: Improved implementation of read/write/copy block.
2019-04-07 17:44:59 -04:00
Fernando Sahmkow
021cd56bc9 Permit a Null Shader in case of a bad host_ptr. 2019-04-07 07:52:01 -04:00
Lioncash
36a1e6a982 core/memory: Remove unused enum constants
These are holdovers from Citra and can be removed.
2019-04-07 03:04:55 -04:00
Lioncash
abae7577d2 core/memory: Remove GetCurrentPageTable()
Now that nothing actually touches the internal page table aside from the
memory subsystem itself, we can remove the accessor to it.
2019-04-07 02:47:37 -04:00
Lioncash
a6a82bb004 arm/arm_dynarmic: Remove unnecessary current_page_table member
Given the page table will always be guaranteed to be that of whatever
the current process is, we no longer need to keep this around.
2019-04-07 02:43:51 -04:00
Lioncash
e779686a76 kernel: Handle page table switching within MakeCurrentProcess()
Centralizes the page table switching to one spot, rather than making
calling code deal with it everywhere.
2019-04-07 01:12:54 -04:00
khang06
945e39471d fix clang-format target when using a path with spaces on windows 2019-04-07 02:10:01 +02:00
Lioncash
7a7ffa602d kernel/server_session: Return a std::pair from CreateSessionPair()
Keeps the return type consistent with the function name. While we're at
it, we can also reduce the amount of boilerplate involved with handling
these by using structured bindings.
2019-04-06 01:42:03 -04:00
Lioncash
04d265562f kernel/server_port: Return a std::pair from CreatePortPair()
Returns the same type that the function name describes.
2019-04-06 01:36:53 -04:00
ReinUsesLisp
ddcb711ee8 maxwell_3d: Reduce severity of ProcessSyncPoint 2019-04-06 02:18:20 -03:00
Lioncash
89c106e31b video_core/textures/convert: Replace include with a forward declaration
Avoids dragging in a direct dependency in a header.
2019-04-06 00:14:36 -04:00
Lioncash
fbf452ab0e video_core/texures/texture: Remove unnecessary includes
Nothing in this header relies on common_funcs or the memory manager.

This gets rid of reliance on indirect inclusions in the OpenGL caches.
2019-04-06 00:03:35 -04:00
bunnei
864280fabc Merge pull request #2317 from FernandoS27/sync
Implement SyncPoint Register in the GPU.
2019-04-05 23:50:54 -04:00
bunnei
7d1c0fd1ad Merge pull request #2325 from lioncash/name
kernel/server_session: Provide a GetName() override
2019-04-05 23:48:13 -04:00
bunnei
fddafa14c8 Merge pull request #2342 from lioncash/warning
common/multi_level_queue: Silence truncation warnings
2019-04-05 23:47:27 -04:00
bunnei
54c7e8e40e Merge pull request #2240 from FearlessTobi/port-4651
Port citra-emu/citra#4651: "gdbstub: Fix some bugs in IsMemoryBreak() and ServeBreak. Add workaround to let watchpoints break into GDB."
2019-04-05 23:46:37 -04:00
bunnei
e3402d976d Merge pull request #2346 from lioncash/header
video_core/engines: Remove unnecessary inclusions where applicable
2019-04-05 23:44:27 -04:00
bunnei
20be92d5e6 memory_manager: Improved implementation of read/write/copy block.
- Fixes graphical issues with Chocobo's Mystery Dungeon EVERY BUDDY!
- Fixes a crash with Mario Tennis Aces
2019-04-05 23:43:34 -04:00
bunnei
89b8801a97 Merge pull request #2350 from lioncash/vmem
video_core/memory_manager: Mark a few member functions with the const qualifier
2019-04-05 23:40:54 -04:00
bunnei
00207cc965 Merge pull request #2340 from lioncash/view
file_sys/fsmitm_romfsbuild: Utilize a string_view in romfs_calc_path_hash
2019-04-05 23:40:16 -04:00
bunnei
e86b26cd2b Merge pull request #2334 from lioncash/override
core: Add missing override specifiers where applicable
2019-04-05 23:39:52 -04:00
bunnei
41890a84be Merge pull request #2347 from lioncash/trunc
video_core/gpu_thread: Silence truncation warning in ThreadManager's constructor
2019-04-05 23:39:31 -04:00
bunnei
23d3cd7604 Merge pull request #2341 from lioncash/compare
file_sys/nca_metadata: Remove unnecessary comparison operators for TitleType
2019-04-05 23:38:37 -04:00
bunnei
d6cddffb78 Merge pull request #2339 from lioncash/rank
service/fsp_srv: Update SaveDataInfo and SaveDataDescriptor structs
2019-04-05 23:36:46 -04:00
bunnei
520e4e5d4b Merge pull request #2327 from ReinUsesLisp/crash-safe-visit
gl_shader_decompiler: Return early when an operation is invalid
2019-04-05 23:36:18 -04:00
bunnei
b8fbd125e6 Merge pull request #2343 from lioncash/todo
file_sys/program_metadata: Remove obsolete TODOs
2019-04-05 23:35:54 -04:00
bunnei
cb2209d06a Merge pull request #2337 from lioncash/temporary
gl_shader_decompiler: Rename GenerateTemporal() to GenerateTemporary()
2019-04-05 23:35:31 -04:00
bunnei
854ac468b9 Merge pull request #2329 from lioncash/sanitize
kernel/svc: Properly sanitize mutex address in WaitProcessWideKeyAtomic
2019-04-05 23:35:06 -04:00
bunnei
150a3c0890 Merge pull request #2344 from lioncash/result
hle/result: Remove unnecessary bitfield entry for ResultCode
2019-04-05 23:34:42 -04:00
bunnei
d9ee5b874c Merge pull request #2349 from lioncash/surface
yuzu/debugger/graphics/graphics_surface: General cleanup
2019-04-05 23:33:45 -04:00
bunnei
8a1bcc3d30 Merge pull request #2351 from lioncash/macro
video_core/macro_interpreter: Simplify GetRegister()
2019-04-05 23:32:26 -04:00
Lioncash
00e7190e29 video_core/macro_interpreter: Remove assertion within FetchParameter()
We can just use .at(), which essentially does the same thing, but with
less code.
2019-04-05 22:56:58 -04:00
Lioncash
1efdb4897e video_core/macro_interpreter: Simplify GetRegister()
Given we already ensure nothing can set the zeroth register in
SetRegister(), we don't need to check if the index is zero and special
case it. We can just access the register normally, since it's already
going to be zero.

We can also replace the assertion with .at() to perform the equivalent
behavior inline as part of the API.
2019-04-05 22:55:13 -04:00
Lioncash
c13fbe6a41 video_core/memory_manager: Make Read() a const qualified member function
Given this doesn't actually alter internal state, this can be made a
const member function.
2019-04-05 20:30:48 -04:00
Lioncash
76ef6e5c2b video_core/memory_manager: Make ReadBlock() a const qualifier member function
Now, since we have a const qualified variant of GetPointer(), we can put
it to use in ReadBlock() to retrieve the source pointer that is passed
into memcpy.

Now block reading may be done from a const context.
2019-04-05 20:28:44 -04:00
Lioncash
34510bcda8 video_core/memory_manager: Add a const qualified variant of GetPointer()
Allows retrieving read-only pointers from a const context externally.
2019-04-05 20:25:28 -04:00
Lioncash
085b388a7a video_core/memory_manager: Make FindFreeRegion() a const member function
This doesn't modify internal state, so it can be made a const member
function.
2019-04-05 20:22:55 -04:00
Lioncash
9dec087fca video_core/memory_manager: Make GpuToCpuAddress() a const member function
This doesn't modify any internal state, so it can be made a const member
function to allow its use in const contexts.
2019-04-05 20:18:29 -04:00
Lioncash
c0e320ad0d yuzu/debugger/graphics_surface: Display error messages for file I/O errors 2019-04-05 19:54:53 -04:00
Lioncash
845607481c yuzu/debugger/graphics_surface: Tidy up SaveSurface
- Use QStringLiteral where applicable.

- Use const where applicable

- Remove unnecessary precondition check (we already assert the pixbuf
  being non null)
2019-04-05 19:33:00 -04:00
Lioncash
bbeb859122 yuzu/debugger/graphics_surface: Clean up connection overload deduction
We can utilize qOverload with the signal connections to make the
function deducing a little less ugly.
2019-04-05 19:26:43 -04:00
Fernando Sahmkow
fc91e21206 Implement SyncPoint Register in the GPU. 2019-04-05 19:19:30 -04:00
Lioncash
9d296f8a35 yuzu/debugger/graphics_surface: Fill in missing surface format listings
Fills in the missing surface types that were marked as unknown. The
order corresponds with the TextureFormat enum within
video_core/texture.h.

We also don't need to all of these strings as translatable (only the
first string, as it's an English word).
2019-04-05 19:09:56 -04:00
Lioncash
30ce9b2b5c video_core/gpu_thread: Silence truncation warning in ThreadManager's constructor
Since c5d41fd812 callback parameters were
changed to use an s64 to represent late cycles instead of an int, so
this was causing a truncation warning to occur here. Changing it to s64
is sufficient to silence the warning.
2019-04-05 18:37:37 -04:00
Lioncash
22f02076c6 video_core/engines: Make memory manager members private
These aren't used externally by anything, so they can be made private
data members.
2019-04-05 18:26:43 -04:00
Lioncash
26223f8124 video_core/engines: Remove unnecessary inclusions where applicable
Replaces header inclusions with forward declarations where applicable
and also removes unused headers within the cpp file. This reduces a few
more dependencies on core/memory.h
2019-04-05 18:26:32 -04:00
Lioncash
5dfcf7cf26 hle/result: Remove unnecessary bitfield entry for ResultCode
This is a hold over from the 3DS error codes in Citra.
2019-04-05 16:34:34 -04:00
Lioncash
37b23efece file_sys/program_metadata: Remove obsolete TODOs
BitField has been trivially copyable since
e99a148628, so we can eliminate these
TODO comments and use ReadObject() directly instead of memcpying the
data.
2019-04-05 15:57:47 -04:00
Lioncash
93b84e9308 common/multi_level_queue: Silence truncation warning in iterator operator++ 2019-04-05 15:35:46 -04:00
Lioncash
33db37e669 common/bit_util: Make CountLeading/CountTrailing functions have the same return types
Makes the return type consistently uniform (like the intrinsics we're
wrapping). This also conveniently silences a truncation warning within
the kernel multi_level_queue.
2019-04-05 15:29:40 -04:00
Lioncash
a1868286b0 file_sys/nca_metadata: Remove unnecessary comparison operators for TitleType
enum class elements from the same enum can already be compared against
one another without the need for explicitly defined comparison
operators.
2019-04-05 15:20:07 -04:00
Lioncash
28e36de56f file_sys/fsmitm_romfsbuild: Utilize a string_view in romfs_calc_path_hash()
The given string instance doesn't need to be copied entirely, we can
just use a view instead.
2019-04-05 15:12:20 -04:00
bunnei
d6b7195192 Merge pull request #2338 from lioncash/fs
filesystem: Use a std::string_view in OpenFile()
2019-04-05 10:52:54 -04:00
bunnei
66be5150d6 Merge pull request #2282 from bunnei/gpu-asynch-v2
gpu_thread: Improve synchronization by using CoreTiming.
2019-04-04 22:38:04 -04:00
bunnei
7c1af3aa10 Merge pull request #2292 from lioncash/nacp
file_sys/control_metadata: Amend naming of members
2019-04-04 22:37:42 -04:00
bunnei
e6a9459b04 Merge pull request #2335 from lioncash/service-unused
hle/service: Resolve unused variable warnings
2019-04-04 22:36:57 -04:00
bunnei
f7d6e08688 Merge pull request #2336 from ReinUsesLisp/txq
gl_shader_decompiler: Fix TXQ types
2019-04-04 22:36:19 -04:00
bunnei
9959c95966 Merge pull request #2331 from lioncash/cache
yuzu/main: Minor adjustments to OnTransferableShaderCacheOpenFile()
2019-04-04 22:35:53 -04:00
bunnei
8502cda17a Merge pull request #2333 from lioncash/video-include
video_core/renderer_opengl: Remove unnecessary includes
2019-04-04 22:35:24 -04:00
bunnei
09789c3ffc Merge pull request #2332 from lioncash/include
yuzu/main: Remove unnecessary includes
2019-04-04 22:34:53 -04:00
Lioncash
15e0c4c4ec filesystem: Use a std::string_view in OpenFile()
Rather than make a full copy of the path, we can just use a string view
and truncate the viewed portion of the string instead of creating a totally
new truncated string.
2019-04-04 20:59:00 -04:00
Lioncash
52746ed8dc gl_shader_decompiler: Rename GenerateTemporal() to GenerateTemporary()
Temporal generally indicates a relation to time, but this is just
creating a temporary, so this isn't really an accurate name for what the
function is actually doing.
2019-04-04 19:35:04 -04:00
ReinUsesLisp
88a3c05b7b gl_shader_decompiler: Fix TXQ types
TXQ returns integer types. Shaders usually do:

R0 = TXQ(); // => int
R0 = static_cast<float>(R0);

If we don't treat it as an integer, it will cast a binary float value as
float - resulting in a corrupted number.
2019-04-04 20:07:11 -03:00
Lioncash
7f506be2ee hle/service: Resolve unused variable warnings
In several places, we have request parsers where there's nothing to
really parse, simply because the HLE function in question operates on
buffers. In these cases we can just remove these instances altogether.

In the other cases, we can retrieve the relevant members from the parser
and at least log them out, giving them some use.
2019-04-04 13:18:09 -04:00
Lioncash
5b0a9f8ba8 core: Add missing override specifiers where applicable
Applies the override specifier where applicable. In the case of
destructors that are  defaulted in their definition, they can
simply be removed.

This also removes the unnecessary inclusions being done in audin_u and
audrec_u, given their close proximity.
2019-04-04 12:19:44 -04:00
Lioncash
3fd5998d84 video_core/renderer_opengl: Remove unnecessary includes
Quite a few unused includes have built up over time, particularly on
core/memory.h. Removing these includes means the source files including
those files will no longer need to be rebuilt if they're changed, making
compilation slightly faster in this scenario.
2019-04-04 12:00:46 -04:00
Lioncash
e8f3d85ea5 yuzu/main: Remove unnecessary includes
While we're at it, don't use <QtGui> and <QtWidgets> and instead include
exactly which headers we actually need.
2019-04-04 11:29:19 -04:00
Lioncash
e5bb07a973 yuzu/main: Use QStringLiteral where applicable within OnTransferableShaderCacheOpenFile()
Allows these strings to have no allocation cost when used at runtime.
2019-04-04 00:12:55 -04:00
Lioncash
5ba5f82082 yuzu/main: Tidy up the error dialog string in OnTransferableShaderCacheOpenFile()
Rather than scream that the file doesn't exist, we can clearly state
what specifically doesn't exist, to avoid ambiguity, and make it easier
to understand for non-primary English speakers/readers.
2019-04-04 00:12:04 -04:00
Lioncash
3f8c9b25d8 yuzu/main: Remove unnecessary string concatenation in OnTransferableShaderCacheOpenFile()
We can just make the trailing portion of the string part of the
formatting, getting rid of the need to make another temporary string.
2019-04-03 23:58:58 -04:00
Lioncash
872d480c60 yuzu/main: Make open_target a QString
Simplifies the amount of string conversions necessary. We also don't
need to log out what occurs here.
2019-04-03 23:55:57 -04:00
Lioncash
ba4e1adda1 yuzu/main: Use static variant of QFile's exists()
There's no need to construct a QFile instance just to check for its
existence.
2019-04-03 23:53:31 -04:00
Lioncash
a973271b8c file_sys/control_metadata: Amend naming of members
Quite a bit of these were out of sync with Switchbrew (and in some cases
entirely wrong). While we're at it, also expand the section of named
members. A segment within the control metadata is used to specify
maximum values for the user, device, and cache storage max sizes and
journal sizes.

These appear to be generally used by the am service (e.g. in
CreateCacheStorage, etc).
2019-04-03 21:18:12 -04:00
Lioncash
c39c8e6982 kernel/svc: Properly sanitize mutex address in WaitProcessWideKeyAtomic
We need to be checking whether or not the given address is within the
kernel address space or if the given address isn't word-aligned and bail
in these scenarios instead of trashing any kernel state.
2019-04-03 20:25:41 -04:00
ReinUsesLisp
78bd66d037 gl_state: Rework to enable individual applies 2019-04-03 20:26:27 -03:00
ReinUsesLisp
06c1f75f21 gl_shader_decompiler: Return early when an operation is invalid 2019-04-03 16:02:09 -03:00
Lioncash
a074363a5d kernel/server_session: Provide a GetName() override
Given server sessions can be given a name, we should allow retrieving
it instead of using the default implementation of GetName(), which would
just return "[UNKNOWN KERNEL OBJECT]".
2019-04-03 10:39:06 -04:00
bunnei
4555b63750 gpu_thread: Improve synchronization by using CoreTiming. 2019-04-01 21:32:39 -04:00
ReinUsesLisp
38658b38b4 gl_shader_decompiler: Hide local definitions inside an anonymous namespace 2019-03-31 00:26:34 -03:00
Mat M
da02946f4f shader_ir/decode: Silent implicit sign conversion warning
Co-Authored-By: ReinUsesLisp <reinuseslisp@airmail.cc>
2019-03-31 00:12:54 -03:00
ReinUsesLisp
e8abe4b77c gl_shader_decompiler: Add AOFFI backing implementation 2019-03-30 02:55:18 -03:00
ReinUsesLisp
cb68ce7c2f shader_ir/decode: Implement AOFFI for TEX and TLD4 2019-03-30 02:53:29 -03:00
ReinUsesLisp
cf4ecc1945 shader_ir: Implement immediate register tracking 2019-03-30 02:53:16 -03:00
unknown
eadc834bb3 gitmodules: Replace taps with spaces 2019-03-29 18:22:08 +01:00
unknown
b4857e326f common/zstd_compression: simplify decompression interface 2019-03-29 18:22:08 +01:00
unknown
aa92da205e gl_shader_disk_cache: Fixup clang format 2019-03-29 18:22:08 +01:00
unknown
35ebbbc167 gl_shader_disk_cache: Use Zstandard for compression 2019-03-29 18:22:08 +01:00
unknown
72477731ed common/zstd_compression: Add Zstandard wrapper 2019-03-29 18:22:08 +01:00
unknown
ca82589350 common: Link libzstd_static 2019-03-29 18:22:07 +01:00
unknown
d85c1141b9 externals: Add libzstd_static to externals CMakeLists.txt 2019-03-29 18:22:07 +01:00
unknown
93de7a7b40 externals: Add Zstandard v1.3.8 2019-03-29 18:22:07 +01:00
unknown
a05f94dcc8 Addressed feedback 2019-03-29 18:22:07 +01:00
unknown
cec7da37b9 core: Do not link LZ4 to core. Use common/data_compression for nso segment decompression instead. 2019-03-29 18:20:48 +01:00
Zach Hilman
552d5071fa patch_manager: Dump NSO name with build ID 2019-03-27 20:09:01 -04:00
Zach Hilman
41d2565f29 game_list: Register content with ContentProvider 2019-03-26 22:05:37 -04:00
Zach Hilman
60f39060c6 core: Port current uses of RegisteredCache to ContentProvider 2019-03-26 22:05:37 -04:00
Zach Hilman
45cb41f517 core: Store system-wide ContentProvider for the emulator 2019-03-26 22:05:37 -04:00
Zach Hilman
a6c7ae6fe8 file_sys: Create ContentProvider interface and default implementations 2019-03-26 22:03:26 -04:00
Adityarup Laha
57a4a2ae0f yuzu: Make hotkeys configurable via the GUI
* Adds a new Hotkeys tab in the Controls group.
* Double-click a Hotkey to rebind it.
2019-03-16 03:55:57 +01:00
Dimitri A
0e7ad1c367 gdbstub: Fix some bugs in IsMemoryBreak() and ServeBreak. Add workaround to let watchpoints break into GDB. (#4651)
* gdbstub: fix IsMemoryBreak() returning false while connected to client

As a result, the only existing codepath for a memory watchpoint hit to break into GDB (InterpeterMainLoop, GDB_BP_CHECK, ARMul_State::RecordBreak) is finally taken,
which exposes incorrect logic* in both RecordBreak and ServeBreak.

* a blank BreakpointAddress structure is passed, which sets r15 (PC) to NULL

* gdbstub: DynCom: default-initialize two members/vars used in conditionals

* gdbstub: DynCom: don't record memory watchpoint hits via RecordBreak()

For now, instead check for GDBStub::IsMemoryBreak() in InterpreterMainLoop and ServeBreak.

Fixes PC being set to a stale/unhit breakpoint address (often zero) when a memory watchpoint (rwatch, watch, awatch) is handled in ServeBreak() and generates a GDB trap.

Reasons for removing a call to RecordBreak() for memory watchpoints:
* The``breakpoint_data`` we pass is typed Execute or None. It describes the predicted next code breakpoint hit relative to PC;

* GDBStub::IsMemoryBreak() returns true if a recent Read/Write operation hit a watchpoint. It doesn't specify which in return, nor does it trace it anywhere. Thus, the only data we could give RecordBreak() is a placeholder BreakpointAddress at offset NULL and type Access. I found the idea silly, compared to simply relying on GDBStub::IsMemoryBreak().

There is currently no measure in the code that remembers the addresses (and types) of any watchpoints that were hit by an instruction, in order to send them to GDB as "extended stop information."
I'm considering an implementation for this.

* gdbstub: Change an ASSERT to DEBUG_ASSERT

I have never seen the (Reg[15] == last_bkpt.address) assert fail in practice, even after several weeks of (locally) developping various branches around GDB.  Only leave it inside Debug builds.
2019-03-15 16:31:06 +01:00
163 changed files with 2562 additions and 1508 deletions

3
.gitmodules vendored
View File

@@ -40,3 +40,6 @@
[submodule "Vulkan-Headers"]
path = externals/Vulkan-Headers
url = https://github.com/KhronosGroup/Vulkan-Headers.git
[submodule "externals/zstd"]
path = externals/zstd
url = https://github.com/facebook/zstd

View File

@@ -309,7 +309,7 @@ if (CLANG_FORMAT)
set(CCOMMENT "Running clang format against all the .h and .cpp files in src/")
if (WIN32)
add_custom_target(clang-format
COMMAND powershell.exe -Command "Get-ChildItem ${SRCS}/* -Include *.cpp,*.h -Recurse | Foreach {${CLANG_FORMAT} -i $_.fullname}"
COMMAND powershell.exe -Command "Get-ChildItem '${SRCS}/*' -Include *.cpp,*.h -Recurse | Foreach {&'${CLANG_FORMAT}' -i $_.fullname}"
COMMENT ${CCOMMENT})
elseif(MINGW)
add_custom_target(clang-format

View File

@@ -49,6 +49,10 @@ add_subdirectory(open_source_archives EXCLUDE_FROM_ALL)
add_library(unicorn-headers INTERFACE)
target_include_directories(unicorn-headers INTERFACE ./unicorn/include)
# Zstandard
add_subdirectory(zstd/build/cmake EXCLUDE_FROM_ALL)
target_include_directories(libzstd_static INTERFACE ./zstd/lib)
# SoundTouch
add_subdirectory(soundtouch)

1
externals/zstd vendored Submodule

Submodule externals/zstd added at 470344d33e

View File

@@ -125,6 +125,8 @@ add_library(common STATIC
uint128.h
vector_math.h
web_result.h
zstd_compression.cpp
zstd_compression.h
)
if(ARCHITECTURE_x86_64)
@@ -138,4 +140,4 @@ endif()
create_target_directory_groups(common)
target_link_libraries(common PUBLIC Boost::boost fmt microprofile)
target_link_libraries(common PRIVATE lz4_static)
target_link_libraries(common PRIVATE lz4_static libzstd_static)

View File

@@ -57,3 +57,21 @@ __declspec(noinline, noreturn)
#define UNIMPLEMENTED_IF(cond) ASSERT_MSG(!(cond), "Unimplemented code!")
#define UNIMPLEMENTED_IF_MSG(cond, ...) ASSERT_MSG(!(cond), __VA_ARGS__)
// If the assert is ignored, execute _b_
#define ASSERT_OR_EXECUTE(_a_, _b_) \
do { \
ASSERT(_a_); \
if (!(_a_)) { \
_b_ \
} \
} while (0)
// If the assert is ignored, execute _b_
#define ASSERT_OR_EXECUTE_MSG(_a_, _b_, ...) \
do { \
ASSERT_MSG(_a_, __VA_ARGS__); \
if (!(_a_)) { \
_b_ \
} \
} while (0)

View File

@@ -32,7 +32,7 @@ inline u32 CountLeadingZeroes32(u32 value) {
return 32;
}
inline u64 CountLeadingZeroes64(u64 value) {
inline u32 CountLeadingZeroes64(u64 value) {
unsigned long leading_zero = 0;
if (_BitScanReverse64(&leading_zero, value) != 0) {
@@ -47,15 +47,15 @@ inline u32 CountLeadingZeroes32(u32 value) {
return 32;
}
return __builtin_clz(value);
return static_cast<u32>(__builtin_clz(value));
}
inline u64 CountLeadingZeroes64(u64 value) {
inline u32 CountLeadingZeroes64(u64 value) {
if (value == 0) {
return 64;
}
return __builtin_clzll(value);
return static_cast<u32>(__builtin_clzll(value));
}
#endif
@@ -70,7 +70,7 @@ inline u32 CountTrailingZeroes32(u32 value) {
return 32;
}
inline u64 CountTrailingZeroes64(u64 value) {
inline u32 CountTrailingZeroes64(u64 value) {
unsigned long trailing_zero = 0;
if (_BitScanForward64(&trailing_zero, value) != 0) {
@@ -85,15 +85,15 @@ inline u32 CountTrailingZeroes32(u32 value) {
return 32;
}
return __builtin_ctz(value);
return static_cast<u32>(__builtin_ctz(value));
}
inline u64 CountTrailingZeroes64(u64 value) {
inline u32 CountTrailingZeroes64(u64 value) {
if (value == 0) {
return 64;
}
return __builtin_ctzll(value);
return static_cast<u32>(__builtin_ctzll(value));
}
#endif

View File

@@ -72,7 +72,7 @@ public:
u64 prios = mlq.used_priorities;
prios &= ~((1ULL << (current_priority + 1)) - 1);
if (prios == 0) {
current_priority = mlq.depth();
current_priority = static_cast<u32>(mlq.depth());
} else {
current_priority = CountTrailingZeroes64(prios);
it = GetBeginItForPrio();

View File

@@ -0,0 +1,53 @@
// Copyright 2019 yuzu Emulator Project
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#pragma once
#include <algorithm>
#include <zstd.h>
#include "common/assert.h"
#include "common/zstd_compression.h"
namespace Common::Compression {
std::vector<u8> CompressDataZSTD(const u8* source, std::size_t source_size, s32 compression_level) {
compression_level = std::clamp(compression_level, 1, ZSTD_maxCLevel());
const std::size_t max_compressed_size = ZSTD_compressBound(source_size);
std::vector<u8> compressed(max_compressed_size);
const std::size_t compressed_size =
ZSTD_compress(compressed.data(), compressed.size(), source, source_size, compression_level);
if (ZSTD_isError(compressed_size)) {
// Compression failed
return {};
}
compressed.resize(compressed_size);
return compressed;
}
std::vector<u8> CompressDataZSTDDefault(const u8* source, std::size_t source_size) {
return CompressDataZSTD(source, source_size, ZSTD_CLEVEL_DEFAULT);
}
std::vector<u8> DecompressDataZSTD(const std::vector<u8>& compressed) {
const std::size_t decompressed_size =
ZSTD_getDecompressedSize(compressed.data(), compressed.size());
std::vector<u8> decompressed(decompressed_size);
const std::size_t uncompressed_result_size = ZSTD_decompress(
decompressed.data(), decompressed.size(), compressed.data(), compressed.size());
if (decompressed_size != uncompressed_result_size || ZSTD_isError(uncompressed_result_size)) {
// Decompression failed
return {};
}
return decompressed;
}
} // namespace Common::Compression

View File

@@ -0,0 +1,42 @@
// Copyright 2019 yuzu Emulator Project
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#include <vector>
#include "common/common_types.h"
namespace Common::Compression {
/**
* Compresses a source memory region with Zstandard and returns the compressed data in a vector.
*
* @param source the uncompressed source memory region.
* @param source_size the size in bytes of the uncompressed source memory region.
* @param compression_level the used compression level. Should be between 1 and 22.
*
* @return the compressed data.
*/
std::vector<u8> CompressDataZSTD(const u8* source, std::size_t source_size, s32 compression_level);
/**
* Compresses a source memory region with Zstandard with the default compression level and returns
* the compressed data in a vector.
*
* @param source the uncompressed source memory region.
* @param source_size the size in bytes of the uncompressed source memory region.
*
* @return the compressed data.
*/
std::vector<u8> CompressDataZSTDDefault(const u8* source, std::size_t source_size);
/**
* Decompresses a source memory region with Zstandard and returns the uncompressed data in a vector.
*
* @param compressed the compressed source memory region.
*
* @return the decompressed data.
*/
std::vector<u8> DecompressDataZSTD(const std::vector<u8>& compressed);
} // namespace Common::Compression

View File

@@ -26,7 +26,6 @@ using Vector = Dynarmic::A64::Vector;
class ARM_Dynarmic_Callbacks : public Dynarmic::A64::UserCallbacks {
public:
explicit ARM_Dynarmic_Callbacks(ARM_Dynarmic& parent) : parent(parent) {}
~ARM_Dynarmic_Callbacks() = default;
u8 MemoryRead8(u64 vaddr) override {
return Memory::Read8(vaddr);
@@ -164,7 +163,6 @@ MICROPROFILE_DEFINE(ARM_Jit_Dynarmic, "ARM JIT", "Dynarmic", MP_RGB(255, 64, 64)
void ARM_Dynarmic::Run() {
MICROPROFILE_SCOPE(ARM_Jit_Dynarmic);
ASSERT(Memory::GetCurrentPageTable() == current_page_table);
jit->Run();
}
@@ -279,7 +277,6 @@ void ARM_Dynarmic::ClearExclusiveState() {
void ARM_Dynarmic::PageTableChanged() {
jit = MakeJit();
current_page_table = Memory::GetCurrentPageTable();
}
DynarmicExclusiveMonitor::DynarmicExclusiveMonitor(std::size_t core_count) : monitor(core_count) {}

View File

@@ -12,10 +12,6 @@
#include "core/arm/exclusive_monitor.h"
#include "core/arm/unicorn/arm_unicorn.h"
namespace Common {
struct PageTable;
}
namespace Core::Timing {
class CoreTiming;
}
@@ -29,7 +25,7 @@ class ARM_Dynarmic final : public ARM_Interface {
public:
ARM_Dynarmic(Timing::CoreTiming& core_timing, ExclusiveMonitor& exclusive_monitor,
std::size_t core_index);
~ARM_Dynarmic();
~ARM_Dynarmic() override;
void MapBackingMemory(VAddr address, std::size_t size, u8* memory,
Kernel::VMAPermission perms) override;
@@ -69,14 +65,12 @@ private:
std::size_t core_index;
Timing::CoreTiming& core_timing;
DynarmicExclusiveMonitor& exclusive_monitor;
Common::PageTable* current_page_table = nullptr;
};
class DynarmicExclusiveMonitor final : public ExclusiveMonitor {
public:
explicit DynarmicExclusiveMonitor(std::size_t core_count);
~DynarmicExclusiveMonitor();
~DynarmicExclusiveMonitor() override;
void SetExclusive(std::size_t core_index, VAddr addr) override;
void ClearExclusive() override;

View File

@@ -192,12 +192,13 @@ void ARM_Unicorn::ExecuteInstructions(int num_instructions) {
CHECKED(uc_emu_start(uc, GetPC(), 1ULL << 63, 0, num_instructions));
core_timing.AddTicks(num_instructions);
if (GDBStub::IsServerEnabled()) {
if (last_bkpt_hit) {
if (last_bkpt_hit && last_bkpt.type == GDBStub::BreakpointType::Execute) {
uc_reg_write(uc, UC_ARM64_REG_PC, &last_bkpt.address);
}
Kernel::Thread* thread = Kernel::GetCurrentThread();
SaveContext(thread->GetContext());
if (last_bkpt_hit || GDBStub::GetCpuStepFlag()) {
if (last_bkpt_hit || GDBStub::IsMemoryBreak() || GDBStub::GetCpuStepFlag()) {
last_bkpt_hit = false;
GDBStub::Break();
GDBStub::SendTrap(thread, 5);

View File

@@ -18,7 +18,7 @@ namespace Core {
class ARM_Unicorn final : public ARM_Interface {
public:
explicit ARM_Unicorn(Timing::CoreTiming& core_timing);
~ARM_Unicorn();
~ARM_Unicorn() override;
void MapBackingMemory(VAddr address, std::size_t size, u8* memory,
Kernel::VMAPermission perms) override;
@@ -50,7 +50,7 @@ private:
uc_engine* uc{};
Timing::CoreTiming& core_timing;
GDBStub::BreakpointAddress last_bkpt{};
bool last_bkpt_hit;
bool last_bkpt_hit = false;
};
} // namespace Core

View File

@@ -17,6 +17,7 @@
#include "core/core_timing.h"
#include "core/cpu_core_manager.h"
#include "core/file_sys/mode.h"
#include "core/file_sys/registered_cache.h"
#include "core/file_sys/vfs_concat.h"
#include "core/file_sys/vfs_real.h"
#include "core/gdbstub/gdbstub.h"
@@ -108,6 +109,8 @@ struct System::Impl {
// Create a default fs if one doesn't already exist.
if (virtual_filesystem == nullptr)
virtual_filesystem = std::make_shared<FileSys::RealVfsFilesystem>();
if (content_provider == nullptr)
content_provider = std::make_unique<FileSys::ContentProviderUnion>();
/// Create default implementations of applets if one is not provided.
if (profile_selector == nullptr)
@@ -249,6 +252,8 @@ struct System::Impl {
Kernel::KernelCore kernel;
/// RealVfsFilesystem instance
FileSys::VirtualFilesystem virtual_filesystem;
/// ContentProviderUnion instance
std::unique_ptr<FileSys::ContentProviderUnion> content_provider;
/// AppLoader used to load the current executing application
std::unique_ptr<Loader::AppLoader> app_loader;
std::unique_ptr<VideoCore::RendererBase> renderer;
@@ -488,6 +493,27 @@ const Frontend::SoftwareKeyboardApplet& System::GetSoftwareKeyboard() const {
return *impl->software_keyboard;
}
void System::SetContentProvider(std::unique_ptr<FileSys::ContentProviderUnion> provider) {
impl->content_provider = std::move(provider);
}
FileSys::ContentProvider& System::GetContentProvider() {
return *impl->content_provider;
}
const FileSys::ContentProvider& System::GetContentProvider() const {
return *impl->content_provider;
}
void System::RegisterContentProvider(FileSys::ContentProviderUnionSlot slot,
FileSys::ContentProvider* provider) {
impl->content_provider->SetSlot(slot, provider);
}
void System::ClearContentProvider(FileSys::ContentProviderUnionSlot slot) {
impl->content_provider->ClearSlot(slot);
}
void System::SetWebBrowser(std::unique_ptr<Frontend::WebBrowserApplet> applet) {
impl->web_browser = std::move(applet);
}

View File

@@ -21,6 +21,9 @@ class WebBrowserApplet;
namespace FileSys {
class CheatList;
class ContentProvider;
class ContentProviderUnion;
enum class ContentProviderUnionSlot;
class VfsFilesystem;
} // namespace FileSys
@@ -270,6 +273,17 @@ public:
Frontend::WebBrowserApplet& GetWebBrowser();
const Frontend::WebBrowserApplet& GetWebBrowser() const;
void SetContentProvider(std::unique_ptr<FileSys::ContentProviderUnion> provider);
FileSys::ContentProvider& GetContentProvider();
const FileSys::ContentProvider& GetContentProvider() const;
void RegisterContentProvider(FileSys::ContentProviderUnionSlot slot,
FileSys::ContentProvider* provider);
void ClearContentProvider(FileSys::ContentProviderUnionSlot slot);
private:
System();

View File

@@ -22,6 +22,7 @@
#include "common/file_util.h"
#include "common/hex_util.h"
#include "common/logging/log.h"
#include "core/core.h"
#include "core/crypto/aes_util.h"
#include "core/crypto/key_manager.h"
#include "core/crypto/partition_data_manager.h"
@@ -794,7 +795,7 @@ void KeyManager::DeriveBase() {
void KeyManager::DeriveETicket(PartitionDataManager& data) {
// ETicket keys
const auto es = Service::FileSystem::GetUnionContents().GetEntry(
const auto es = Core::System::GetInstance().GetContentProvider().GetEntry(
0x0100000000000033, FileSys::ContentRecordType::Program);
if (es == nullptr)

View File

@@ -67,7 +67,7 @@ std::string NACP::GetDeveloperName(Language language) const {
}
u64 NACP::GetTitleId() const {
return raw.title_id;
return raw.save_data_owner_id;
}
u64 NACP::GetDLCBaseTitleId() const {
@@ -80,11 +80,11 @@ std::string NACP::GetVersionString() const {
}
u64 NACP::GetDefaultNormalSaveSize() const {
return raw.normal_save_data_size;
return raw.user_account_save_data_size;
}
u64 NACP::GetDefaultJournalSaveSize() const {
return raw.journal_sava_data_size;
return raw.user_account_save_data_journal_size;
}
std::vector<u8> NACP::GetRawBytes() const {

View File

@@ -38,23 +38,35 @@ struct RawNACP {
u8 video_capture_mode;
bool data_loss_confirmation;
INSERT_PADDING_BYTES(1);
u64_le title_id;
u64_le presence_group_id;
std::array<u8, 0x20> rating_age;
std::array<char, 0x10> version_string;
u64_le dlc_base_title_id;
u64_le title_id_2;
u64_le normal_save_data_size;
u64_le journal_sava_data_size;
INSERT_PADDING_BYTES(0x18);
u64_le product_code;
u64_le save_data_owner_id;
u64_le user_account_save_data_size;
u64_le user_account_save_data_journal_size;
u64_le device_save_data_size;
u64_le device_save_data_journal_size;
u64_le bcat_delivery_cache_storage_size;
char application_error_code_category[8];
std::array<u64_le, 0x8> local_communication;
u8 logo_type;
u8 logo_handling;
bool runtime_add_on_content_install;
INSERT_PADDING_BYTES(5);
u64_le title_id_update;
std::array<u8, 0x40> bcat_passphrase;
INSERT_PADDING_BYTES(0xEC0);
u64_le seed_for_pseudo_device_id;
std::array<u8, 0x41> bcat_passphrase;
INSERT_PADDING_BYTES(7);
u64_le user_account_save_data_max_size;
u64_le user_account_save_data_max_journal_size;
u64_le device_save_data_max_size;
u64_le device_save_data_max_journal_size;
u64_le temporary_storage_size;
u64_le cache_storage_size;
u64_le cache_storage_journal_size;
u64_le cache_storage_data_and_journal_max_size;
u64_le cache_storage_max_index;
INSERT_PADDING_BYTES(0xE70);
};
static_assert(sizeof(RawNACP) == 0x4000, "RawNACP has incorrect size.");

View File

@@ -23,6 +23,7 @@
*/
#include <cstring>
#include <string_view>
#include "common/alignment.h"
#include "common/assert.h"
#include "core/file_sys/fsmitm_romfsbuild.h"
@@ -97,7 +98,8 @@ struct RomFSBuildFileContext {
VirtualFile source;
};
static u32 romfs_calc_path_hash(u32 parent, std::string path, u32 start, std::size_t path_len) {
static u32 romfs_calc_path_hash(u32 parent, std::string_view path, u32 start,
std::size_t path_len) {
u32 hash = parent ^ 123456789;
for (u32 i = 0; i < path_len; i++) {
hash = (hash >> 5) | (hash << 27);

View File

@@ -10,14 +10,6 @@
namespace FileSys {
bool operator>=(TitleType lhs, TitleType rhs) {
return static_cast<std::size_t>(lhs) >= static_cast<std::size_t>(rhs);
}
bool operator<=(TitleType lhs, TitleType rhs) {
return static_cast<std::size_t>(lhs) <= static_cast<std::size_t>(rhs);
}
CNMT::CNMT(VirtualFile file) {
if (file->ReadObject(&header) != sizeof(CNMTHeader))
return;

View File

@@ -29,9 +29,6 @@ enum class TitleType : u8 {
DeltaTitle = 0x83,
};
bool operator>=(TitleType lhs, TitleType rhs);
bool operator<=(TitleType lhs, TitleType rhs);
enum class ContentRecordType : u8 {
Meta = 0,
Program = 1,

View File

@@ -10,6 +10,7 @@
#include "common/file_util.h"
#include "common/hex_util.h"
#include "common/logging/log.h"
#include "core/core.h"
#include "core/file_sys/content_archive.h"
#include "core/file_sys/control_metadata.h"
#include "core/file_sys/ips_layer.h"
@@ -69,7 +70,7 @@ VirtualDir PatchManager::PatchExeFS(VirtualDir exefs) const {
}
}
const auto installed = Service::FileSystem::GetUnionContents();
const auto& installed = Core::System::GetInstance().GetContentProvider();
const auto& disabled = Settings::values.disabled_addons[title_id];
const auto update_disabled =
@@ -155,7 +156,7 @@ std::vector<VirtualFile> PatchManager::CollectPatches(const std::vector<VirtualD
return out;
}
std::vector<u8> PatchManager::PatchNSO(const std::vector<u8>& nso) const {
std::vector<u8> PatchManager::PatchNSO(const std::vector<u8>& nso, const std::string& name) const {
if (nso.size() < sizeof(Loader::NSOHeader)) {
return nso;
}
@@ -171,18 +172,19 @@ std::vector<u8> PatchManager::PatchNSO(const std::vector<u8>& nso) const {
const auto build_id = build_id_raw.substr(0, build_id_raw.find_last_not_of('0') + 1);
if (Settings::values.dump_nso) {
LOG_INFO(Loader, "Dumping NSO for build_id={}, title_id={:016X}", build_id, title_id);
LOG_INFO(Loader, "Dumping NSO for name={}, build_id={}, title_id={:016X}", name, build_id,
title_id);
const auto dump_dir = Service::FileSystem::GetModificationDumpRoot(title_id);
if (dump_dir != nullptr) {
const auto nso_dir = GetOrCreateDirectoryRelative(dump_dir, "/nso");
const auto file = nso_dir->CreateFile(fmt::format("{}.nso", build_id));
const auto file = nso_dir->CreateFile(fmt::format("{}-{}.nso", name, build_id));
file->Resize(nso.size());
file->WriteBytes(nso);
}
}
LOG_INFO(Loader, "Patching NSO for build_id={}", build_id);
LOG_INFO(Loader, "Patching NSO for name={}, build_id={}", name, build_id);
const auto load_dir = Service::FileSystem::GetModificationLoadRoot(title_id);
auto patch_dirs = load_dir->GetSubdirectories();
@@ -345,7 +347,7 @@ VirtualFile PatchManager::PatchRomFS(VirtualFile romfs, u64 ivfc_offset, Content
if (romfs == nullptr)
return romfs;
const auto installed = Service::FileSystem::GetUnionContents();
const auto& installed = Core::System::GetInstance().GetContentProvider();
// Game Updates
const auto update_tid = GetUpdateTitleID(title_id);
@@ -392,7 +394,7 @@ static bool IsDirValidAndNonEmpty(const VirtualDir& dir) {
std::map<std::string, std::string, std::less<>> PatchManager::GetPatchVersionNames(
VirtualFile update_raw) const {
std::map<std::string, std::string, std::less<>> out;
const auto installed = Service::FileSystem::GetUnionContents();
const auto& installed = Core::System::GetInstance().GetContentProvider();
const auto& disabled = Settings::values.disabled_addons[title_id];
// Game Updates
@@ -466,10 +468,10 @@ std::map<std::string, std::string, std::less<>> PatchManager::GetPatchVersionNam
// DLC
const auto dlc_entries = installed.ListEntriesFilter(TitleType::AOC, ContentRecordType::Data);
std::vector<RegisteredCacheEntry> dlc_match;
std::vector<ContentProviderEntry> 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) {
[this, &installed](const ContentProviderEntry& entry) {
return (entry.title_id & DLC_BASE_TITLE_ID_MASK) == title_id &&
installed.GetEntry(entry)->GetStatus() == Loader::ResultStatus::Success;
});
@@ -492,7 +494,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& installed = Core::System::GetInstance().GetContentProvider();
const auto base_control_nca = installed.GetEntry(title_id, ContentRecordType::Control);
if (base_control_nca == nullptr)

View File

@@ -44,7 +44,7 @@ public:
// Currently tracked NSO patches:
// - IPS
// - IPSwitch
std::vector<u8> PatchNSO(const std::vector<u8>& nso) const;
std::vector<u8> PatchNSO(const std::vector<u8>& nso, const std::string& name) const;
// Checks to see if PatchNSO() will have any effect given the NSO's build ID.
// Used to prevent expensive copies in NSO loader.

View File

@@ -3,7 +3,6 @@
// Refer to the license.txt file included.
#include <cstddef>
#include <cstring>
#include <vector>
#include "common/logging/log.h"
@@ -17,28 +16,30 @@ ProgramMetadata::ProgramMetadata() = default;
ProgramMetadata::~ProgramMetadata() = default;
Loader::ResultStatus ProgramMetadata::Load(VirtualFile file) {
std::size_t total_size = static_cast<std::size_t>(file->GetSize());
if (total_size < sizeof(Header))
const std::size_t total_size = file->GetSize();
if (total_size < sizeof(Header)) {
return Loader::ResultStatus::ErrorBadNPDMHeader;
}
// TODO(DarkLordZach): Use ReadObject when Header/AcidHeader becomes trivially copyable.
std::vector<u8> npdm_header_data = file->ReadBytes(sizeof(Header));
if (sizeof(Header) != npdm_header_data.size())
if (sizeof(Header) != file->ReadObject(&npdm_header)) {
return Loader::ResultStatus::ErrorBadNPDMHeader;
std::memcpy(&npdm_header, npdm_header_data.data(), sizeof(Header));
}
std::vector<u8> acid_header_data = file->ReadBytes(sizeof(AcidHeader), npdm_header.acid_offset);
if (sizeof(AcidHeader) != acid_header_data.size())
if (sizeof(AcidHeader) != file->ReadObject(&acid_header, npdm_header.acid_offset)) {
return Loader::ResultStatus::ErrorBadACIDHeader;
std::memcpy(&acid_header, acid_header_data.data(), sizeof(AcidHeader));
}
if (sizeof(AciHeader) != file->ReadObject(&aci_header, npdm_header.aci_offset))
if (sizeof(AciHeader) != file->ReadObject(&aci_header, npdm_header.aci_offset)) {
return Loader::ResultStatus::ErrorBadACIHeader;
}
if (sizeof(FileAccessControl) != file->ReadObject(&acid_file_access, acid_header.fac_offset))
if (sizeof(FileAccessControl) != file->ReadObject(&acid_file_access, acid_header.fac_offset)) {
return Loader::ResultStatus::ErrorBadFileAccessControl;
if (sizeof(FileAccessHeader) != file->ReadObject(&aci_file_access, aci_header.fah_offset))
}
if (sizeof(FileAccessHeader) != file->ReadObject(&aci_file_access, aci_header.fah_offset)) {
return Loader::ResultStatus::ErrorBadFileAccessHeader;
}
aci_kernel_capabilities.resize(aci_header.kac_size / sizeof(u32));
const u64 read_size = aci_header.kac_size;

View File

@@ -58,7 +58,6 @@ public:
void Print() const;
private:
// TODO(DarkLordZach): BitField is not trivially copyable.
struct Header {
std::array<char, 4> magic;
std::array<u8, 8> reserved;
@@ -85,7 +84,6 @@ private:
static_assert(sizeof(Header) == 0x80, "NPDM header structure size is wrong");
// TODO(DarkLordZach): BitField is not trivially copyable.
struct AcidHeader {
std::array<u8, 0x100> signature;
std::array<u8, 0x100> nca_modulus;

View File

@@ -23,19 +23,19 @@ namespace FileSys {
// The size of blocks to use when vfs raw copying into nand.
constexpr size_t VFS_RC_LARGE_COPY_BLOCK = 0x400000;
std::string RegisteredCacheEntry::DebugInfo() const {
std::string ContentProviderEntry::DebugInfo() const {
return fmt::format("title_id={:016X}, content_type={:02X}", title_id, static_cast<u8>(type));
}
bool operator<(const RegisteredCacheEntry& lhs, const RegisteredCacheEntry& rhs) {
bool operator<(const ContentProviderEntry& lhs, const ContentProviderEntry& rhs) {
return (lhs.title_id < rhs.title_id) || (lhs.title_id == rhs.title_id && lhs.type < rhs.type);
}
bool operator==(const RegisteredCacheEntry& lhs, const RegisteredCacheEntry& rhs) {
bool operator==(const ContentProviderEntry& lhs, const ContentProviderEntry& rhs) {
return std::tie(lhs.title_id, lhs.type) == std::tie(rhs.title_id, rhs.type);
}
bool operator!=(const RegisteredCacheEntry& lhs, const RegisteredCacheEntry& rhs) {
bool operator!=(const ContentProviderEntry& lhs, const ContentProviderEntry& rhs) {
return !operator==(lhs, rhs);
}
@@ -84,7 +84,7 @@ static std::string GetCNMTName(TitleType type, u64 title_id) {
return fmt::format("{}_{:016x}.cnmt", TITLE_TYPE_NAMES[index], title_id);
}
static ContentRecordType GetCRTypeFromNCAType(NCAContentType type) {
ContentRecordType GetCRTypeFromNCAType(NCAContentType type) {
switch (type) {
case NCAContentType::Program:
// TODO(DarkLordZach): Differentiate between Program and Patch
@@ -104,6 +104,28 @@ static ContentRecordType GetCRTypeFromNCAType(NCAContentType type) {
}
}
ContentProvider::~ContentProvider() = default;
bool ContentProvider::HasEntry(ContentProviderEntry entry) const {
return HasEntry(entry.title_id, entry.type);
}
VirtualFile ContentProvider::GetEntryUnparsed(ContentProviderEntry entry) const {
return GetEntryUnparsed(entry.title_id, entry.type);
}
VirtualFile ContentProvider::GetEntryRaw(ContentProviderEntry entry) const {
return GetEntryRaw(entry.title_id, entry.type);
}
std::unique_ptr<NCA> ContentProvider::GetEntry(ContentProviderEntry entry) const {
return GetEntry(entry.title_id, entry.type);
}
std::vector<ContentProviderEntry> ContentProvider::ListEntries() const {
return ListEntriesFilter(std::nullopt, std::nullopt, std::nullopt);
}
VirtualFile RegisteredCache::OpenFileOrDirectoryConcat(const VirtualDir& dir,
std::string_view path) const {
const auto file = dir->GetFileRelative(path);
@@ -161,8 +183,8 @@ VirtualFile RegisteredCache::GetFileAtID(NcaID id) const {
return file;
}
static std::optional<NcaID> CheckMapForContentRecord(
const boost::container::flat_map<u64, CNMT>& map, u64 title_id, ContentRecordType type) {
static std::optional<NcaID> CheckMapForContentRecord(const std::map<u64, CNMT>& map, u64 title_id,
ContentRecordType type) {
if (map.find(title_id) == map.end())
return {};
@@ -268,7 +290,7 @@ void RegisteredCache::Refresh() {
AccumulateYuzuMeta();
}
RegisteredCache::RegisteredCache(VirtualDir dir_, RegisteredCacheParsingFunction parsing_function)
RegisteredCache::RegisteredCache(VirtualDir dir_, ContentProviderParsingFunction parsing_function)
: dir(std::move(dir_)), parser(std::move(parsing_function)) {
Refresh();
}
@@ -279,19 +301,11 @@ bool RegisteredCache::HasEntry(u64 title_id, ContentRecordType type) const {
return GetEntryRaw(title_id, type) != nullptr;
}
bool RegisteredCache::HasEntry(RegisteredCacheEntry entry) const {
return GetEntryRaw(entry) != nullptr;
}
VirtualFile RegisteredCache::GetEntryUnparsed(u64 title_id, ContentRecordType type) const {
const auto id = GetNcaIDFromMetadata(title_id, type);
return id ? GetFileAtID(*id) : nullptr;
}
VirtualFile RegisteredCache::GetEntryUnparsed(RegisteredCacheEntry entry) const {
return GetEntryUnparsed(entry.title_id, entry.type);
}
std::optional<u32> RegisteredCache::GetEntryVersion(u64 title_id) const {
const auto meta_iter = meta.find(title_id);
if (meta_iter != meta.end())
@@ -309,10 +323,6 @@ VirtualFile RegisteredCache::GetEntryRaw(u64 title_id, ContentRecordType type) c
return id ? parser(GetFileAtID(*id), *id) : nullptr;
}
VirtualFile RegisteredCache::GetEntryRaw(RegisteredCacheEntry entry) const {
return GetEntryRaw(entry.title_id, entry.type);
}
std::unique_ptr<NCA> RegisteredCache::GetEntry(u64 title_id, ContentRecordType type) const {
const auto raw = GetEntryRaw(title_id, type);
if (raw == nullptr)
@@ -320,10 +330,6 @@ std::unique_ptr<NCA> RegisteredCache::GetEntry(u64 title_id, ContentRecordType t
return std::make_unique<NCA>(raw, nullptr, 0, keys);
}
std::unique_ptr<NCA> RegisteredCache::GetEntry(RegisteredCacheEntry entry) const {
return GetEntry(entry.title_id, entry.type);
}
template <typename T>
void RegisteredCache::IterateAllMetadata(
std::vector<T>& out, std::function<T(const CNMT&, const ContentRecord&)> proc,
@@ -348,25 +354,14 @@ void RegisteredCache::IterateAllMetadata(
}
}
std::vector<RegisteredCacheEntry> RegisteredCache::ListEntries() const {
std::vector<RegisteredCacheEntry> out;
IterateAllMetadata<RegisteredCacheEntry>(
out,
[](const CNMT& c, const ContentRecord& r) {
return RegisteredCacheEntry{c.GetTitleID(), r.type};
},
[](const CNMT& c, const ContentRecord& r) { return true; });
return out;
}
std::vector<RegisteredCacheEntry> RegisteredCache::ListEntriesFilter(
std::vector<ContentProviderEntry> RegisteredCache::ListEntriesFilter(
std::optional<TitleType> title_type, std::optional<ContentRecordType> record_type,
std::optional<u64> title_id) const {
std::vector<RegisteredCacheEntry> out;
IterateAllMetadata<RegisteredCacheEntry>(
std::vector<ContentProviderEntry> out;
IterateAllMetadata<ContentProviderEntry>(
out,
[](const CNMT& c, const ContentRecord& r) {
return RegisteredCacheEntry{c.GetTitleID(), r.type};
return ContentProviderEntry{c.GetTitleID(), r.type};
},
[&title_type, &record_type, &title_id](const CNMT& c, const ContentRecord& r) {
if (title_type && *title_type != c.GetType())
@@ -521,37 +516,56 @@ bool RegisteredCache::RawInstallYuzuMeta(const CNMT& cnmt) {
}) != yuzu_meta.end();
}
RegisteredCacheUnion::RegisteredCacheUnion(std::vector<RegisteredCache*> caches)
: caches(std::move(caches)) {}
ContentProviderUnion::~ContentProviderUnion() = default;
void RegisteredCacheUnion::Refresh() {
for (const auto& c : caches)
c->Refresh();
void ContentProviderUnion::SetSlot(ContentProviderUnionSlot slot, ContentProvider* provider) {
providers[slot] = provider;
}
bool RegisteredCacheUnion::HasEntry(u64 title_id, ContentRecordType type) const {
return std::any_of(caches.begin(), caches.end(), [title_id, type](const auto& cache) {
return cache->HasEntry(title_id, type);
});
void ContentProviderUnion::ClearSlot(ContentProviderUnionSlot slot) {
providers[slot] = nullptr;
}
bool RegisteredCacheUnion::HasEntry(RegisteredCacheEntry entry) const {
return HasEntry(entry.title_id, entry.type);
void ContentProviderUnion::Refresh() {
for (auto& provider : providers) {
if (provider.second == nullptr)
continue;
provider.second->Refresh();
}
}
std::optional<u32> RegisteredCacheUnion::GetEntryVersion(u64 title_id) const {
for (const auto& c : caches) {
const auto res = c->GetEntryVersion(title_id);
if (res)
bool ContentProviderUnion::HasEntry(u64 title_id, ContentRecordType type) const {
for (const auto& provider : providers) {
if (provider.second == nullptr)
continue;
if (provider.second->HasEntry(title_id, type))
return true;
}
return false;
}
std::optional<u32> ContentProviderUnion::GetEntryVersion(u64 title_id) const {
for (const auto& provider : providers) {
if (provider.second == nullptr)
continue;
const auto res = provider.second->GetEntryVersion(title_id);
if (res != std::nullopt)
return res;
}
return {};
return std::nullopt;
}
VirtualFile RegisteredCacheUnion::GetEntryUnparsed(u64 title_id, ContentRecordType type) const {
for (const auto& c : caches) {
const auto res = c->GetEntryUnparsed(title_id, type);
VirtualFile ContentProviderUnion::GetEntryUnparsed(u64 title_id, ContentRecordType type) const {
for (const auto& provider : providers) {
if (provider.second == nullptr)
continue;
const auto res = provider.second->GetEntryUnparsed(title_id, type);
if (res != nullptr)
return res;
}
@@ -559,13 +573,12 @@ VirtualFile RegisteredCacheUnion::GetEntryUnparsed(u64 title_id, ContentRecordTy
return nullptr;
}
VirtualFile RegisteredCacheUnion::GetEntryUnparsed(RegisteredCacheEntry entry) const {
return GetEntryUnparsed(entry.title_id, entry.type);
}
VirtualFile ContentProviderUnion::GetEntryRaw(u64 title_id, ContentRecordType type) const {
for (const auto& provider : providers) {
if (provider.second == nullptr)
continue;
VirtualFile RegisteredCacheUnion::GetEntryRaw(u64 title_id, ContentRecordType type) const {
for (const auto& c : caches) {
const auto res = c->GetEntryRaw(title_id, type);
const auto res = provider.second->GetEntryRaw(title_id, type);
if (res != nullptr)
return res;
}
@@ -573,30 +586,30 @@ VirtualFile RegisteredCacheUnion::GetEntryRaw(u64 title_id, ContentRecordType ty
return nullptr;
}
VirtualFile RegisteredCacheUnion::GetEntryRaw(RegisteredCacheEntry entry) const {
return GetEntryRaw(entry.title_id, entry.type);
std::unique_ptr<NCA> ContentProviderUnion::GetEntry(u64 title_id, ContentRecordType type) const {
for (const auto& provider : providers) {
if (provider.second == nullptr)
continue;
auto res = provider.second->GetEntry(title_id, type);
if (res != nullptr)
return res;
}
return nullptr;
}
std::unique_ptr<NCA> RegisteredCacheUnion::GetEntry(u64 title_id, ContentRecordType type) const {
const auto raw = GetEntryRaw(title_id, type);
if (raw == nullptr)
return nullptr;
return std::make_unique<NCA>(raw);
}
std::vector<ContentProviderEntry> ContentProviderUnion::ListEntriesFilter(
std::optional<TitleType> title_type, std::optional<ContentRecordType> record_type,
std::optional<u64> title_id) const {
std::vector<ContentProviderEntry> out;
std::unique_ptr<NCA> RegisteredCacheUnion::GetEntry(RegisteredCacheEntry entry) const {
return GetEntry(entry.title_id, entry.type);
}
for (const auto& provider : providers) {
if (provider.second == nullptr)
continue;
std::vector<RegisteredCacheEntry> RegisteredCacheUnion::ListEntries() const {
std::vector<RegisteredCacheEntry> out;
for (const auto& c : caches) {
c->IterateAllMetadata<RegisteredCacheEntry>(
out,
[](const CNMT& c, const ContentRecord& r) {
return RegisteredCacheEntry{c.GetTitleID(), r.type};
},
[](const CNMT& c, const ContentRecord& r) { return true; });
const auto vec = provider.second->ListEntriesFilter(title_type, record_type, title_id);
std::copy(vec.begin(), vec.end(), std::back_inserter(out));
}
std::sort(out.begin(), out.end());
@@ -604,25 +617,87 @@ std::vector<RegisteredCacheEntry> RegisteredCacheUnion::ListEntries() const {
return out;
}
std::vector<RegisteredCacheEntry> RegisteredCacheUnion::ListEntriesFilter(
std::vector<std::pair<ContentProviderUnionSlot, ContentProviderEntry>>
ContentProviderUnion::ListEntriesFilterOrigin(std::optional<ContentProviderUnionSlot> origin,
std::optional<TitleType> title_type,
std::optional<ContentRecordType> record_type,
std::optional<u64> title_id) const {
std::vector<std::pair<ContentProviderUnionSlot, ContentProviderEntry>> out;
for (const auto& provider : providers) {
if (provider.second == nullptr)
continue;
if (origin.has_value() && *origin != provider.first)
continue;
const auto vec = provider.second->ListEntriesFilter(title_type, record_type, title_id);
std::transform(vec.begin(), vec.end(), std::back_inserter(out),
[&provider](const ContentProviderEntry& entry) {
return std::make_pair(provider.first, entry);
});
}
std::sort(out.begin(), out.end());
out.erase(std::unique(out.begin(), out.end()), out.end());
return out;
}
ManualContentProvider::~ManualContentProvider() = default;
void ManualContentProvider::AddEntry(TitleType title_type, ContentRecordType content_type,
u64 title_id, VirtualFile file) {
entries.insert_or_assign({title_type, content_type, title_id}, file);
}
void ManualContentProvider::ClearAllEntries() {
entries.clear();
}
void ManualContentProvider::Refresh() {}
bool ManualContentProvider::HasEntry(u64 title_id, ContentRecordType type) const {
return GetEntryRaw(title_id, type) != nullptr;
}
std::optional<u32> ManualContentProvider::GetEntryVersion(u64 title_id) const {
return std::nullopt;
}
VirtualFile ManualContentProvider::GetEntryUnparsed(u64 title_id, ContentRecordType type) const {
return GetEntryRaw(title_id, type);
}
VirtualFile ManualContentProvider::GetEntryRaw(u64 title_id, ContentRecordType type) const {
const auto iter =
std::find_if(entries.begin(), entries.end(), [title_id, type](const auto& entry) {
const auto [title_type, content_type, e_title_id] = entry.first;
return content_type == type && e_title_id == title_id;
});
if (iter == entries.end())
return nullptr;
return iter->second;
}
std::unique_ptr<NCA> ManualContentProvider::GetEntry(u64 title_id, ContentRecordType type) const {
const auto res = GetEntryRaw(title_id, type);
if (res == nullptr)
return nullptr;
return std::make_unique<NCA>(res, nullptr, 0, keys);
}
std::vector<ContentProviderEntry> ManualContentProvider::ListEntriesFilter(
std::optional<TitleType> title_type, std::optional<ContentRecordType> record_type,
std::optional<u64> title_id) const {
std::vector<RegisteredCacheEntry> out;
for (const auto& c : caches) {
c->IterateAllMetadata<RegisteredCacheEntry>(
out,
[](const CNMT& c, const ContentRecord& r) {
return RegisteredCacheEntry{c.GetTitleID(), r.type};
},
[&title_type, &record_type, &title_id](const CNMT& c, const ContentRecord& r) {
if (title_type && *title_type != c.GetType())
return false;
if (record_type && *record_type != r.type)
return false;
if (title_id && *title_id != c.GetTitleID())
return false;
return true;
});
std::vector<ContentProviderEntry> out;
for (const auto& entry : entries) {
const auto [e_title_type, e_content_type, e_title_id] = entry.first;
if ((title_type == std::nullopt || e_title_type == *title_type) &&
(record_type == std::nullopt || e_content_type == *record_type) &&
(title_id == std::nullopt || e_title_id == *title_id)) {
out.emplace_back(ContentProviderEntry{e_title_id, e_content_type});
}
}
std::sort(out.begin(), out.end());

View File

@@ -21,12 +21,13 @@ class NSP;
class XCI;
enum class ContentRecordType : u8;
enum class NCAContentType : u8;
enum class TitleType : u8;
struct ContentRecord;
using NcaID = std::array<u8, 0x10>;
using RegisteredCacheParsingFunction = std::function<VirtualFile(const VirtualFile&, const NcaID&)>;
using ContentProviderParsingFunction = std::function<VirtualFile(const VirtualFile&, const NcaID&)>;
using VfsCopyFunction = std::function<bool(const VirtualFile&, const VirtualFile&, size_t)>;
enum class InstallResult {
@@ -36,7 +37,7 @@ enum class InstallResult {
ErrorMetaFailed,
};
struct RegisteredCacheEntry {
struct ContentProviderEntry {
u64 title_id;
ContentRecordType type;
@@ -47,12 +48,46 @@ constexpr u64 GetUpdateTitleID(u64 base_title_id) {
return base_title_id | 0x800;
}
ContentRecordType GetCRTypeFromNCAType(NCAContentType type);
// boost flat_map requires operator< for O(log(n)) lookups.
bool operator<(const RegisteredCacheEntry& lhs, const RegisteredCacheEntry& rhs);
bool operator<(const ContentProviderEntry& lhs, const ContentProviderEntry& rhs);
// std unique requires operator== to identify duplicates.
bool operator==(const RegisteredCacheEntry& lhs, const RegisteredCacheEntry& rhs);
bool operator!=(const RegisteredCacheEntry& lhs, const RegisteredCacheEntry& rhs);
bool operator==(const ContentProviderEntry& lhs, const ContentProviderEntry& rhs);
bool operator!=(const ContentProviderEntry& lhs, const ContentProviderEntry& rhs);
class ContentProvider {
public:
virtual ~ContentProvider();
virtual void Refresh() = 0;
virtual bool HasEntry(u64 title_id, ContentRecordType type) const = 0;
virtual bool HasEntry(ContentProviderEntry entry) const;
virtual std::optional<u32> GetEntryVersion(u64 title_id) const = 0;
virtual VirtualFile GetEntryUnparsed(u64 title_id, ContentRecordType type) const = 0;
virtual VirtualFile GetEntryUnparsed(ContentProviderEntry entry) const;
virtual VirtualFile GetEntryRaw(u64 title_id, ContentRecordType type) const = 0;
virtual VirtualFile GetEntryRaw(ContentProviderEntry entry) const;
virtual std::unique_ptr<NCA> GetEntry(u64 title_id, ContentRecordType type) const = 0;
virtual std::unique_ptr<NCA> GetEntry(ContentProviderEntry entry) const;
virtual std::vector<ContentProviderEntry> ListEntries() const;
// If a parameter is not std::nullopt, it will be filtered for from all entries.
virtual std::vector<ContentProviderEntry> ListEntriesFilter(
std::optional<TitleType> title_type = {}, std::optional<ContentRecordType> record_type = {},
std::optional<u64> title_id = {}) const = 0;
protected:
// A single instance of KeyManager to be used by GetEntry()
Core::Crypto::KeyManager keys;
};
/*
* A class that catalogues NCAs in the registered directory structure.
@@ -67,39 +102,32 @@ bool operator!=(const RegisteredCacheEntry& lhs, const RegisteredCacheEntry& rhs
* (This impl also supports substituting the nca dir for an nca file, as that's more convenient
* when 4GB splitting can be ignored.)
*/
class RegisteredCache {
friend class RegisteredCacheUnion;
class RegisteredCache : public ContentProvider {
public:
// Parsing function defines the conversion from raw file to NCA. If there are other steps
// besides creating the NCA from the file (e.g. NAX0 on SD Card), that should go in a custom
// parsing function.
explicit RegisteredCache(VirtualDir dir,
RegisteredCacheParsingFunction parsing_function =
ContentProviderParsingFunction parsing_function =
[](const VirtualFile& file, const NcaID& id) { return file; });
~RegisteredCache();
~RegisteredCache() override;
void Refresh();
void Refresh() override;
bool HasEntry(u64 title_id, ContentRecordType type) const;
bool HasEntry(RegisteredCacheEntry entry) const;
bool HasEntry(u64 title_id, ContentRecordType type) const override;
std::optional<u32> GetEntryVersion(u64 title_id) const;
std::optional<u32> GetEntryVersion(u64 title_id) const override;
VirtualFile GetEntryUnparsed(u64 title_id, ContentRecordType type) const;
VirtualFile GetEntryUnparsed(RegisteredCacheEntry entry) const;
VirtualFile GetEntryUnparsed(u64 title_id, ContentRecordType type) const override;
VirtualFile GetEntryRaw(u64 title_id, ContentRecordType type) const;
VirtualFile GetEntryRaw(RegisteredCacheEntry entry) const;
VirtualFile GetEntryRaw(u64 title_id, ContentRecordType type) const override;
std::unique_ptr<NCA> GetEntry(u64 title_id, ContentRecordType type) const;
std::unique_ptr<NCA> GetEntry(RegisteredCacheEntry entry) const;
std::unique_ptr<NCA> GetEntry(u64 title_id, ContentRecordType type) const override;
std::vector<RegisteredCacheEntry> ListEntries() const;
// If a parameter is not std::nullopt, it will be filtered for from all entries.
std::vector<RegisteredCacheEntry> ListEntriesFilter(
std::vector<ContentProviderEntry> ListEntriesFilter(
std::optional<TitleType> title_type = {}, std::optional<ContentRecordType> record_type = {},
std::optional<u64> title_id = {}) const;
std::optional<u64> title_id = {}) const override;
// 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.
@@ -131,46 +159,70 @@ private:
bool RawInstallYuzuMeta(const CNMT& cnmt);
VirtualDir dir;
RegisteredCacheParsingFunction parser;
Core::Crypto::KeyManager keys;
ContentProviderParsingFunction parser;
// maps tid -> NcaID of meta
boost::container::flat_map<u64, NcaID> meta_id;
std::map<u64, NcaID> meta_id;
// maps tid -> meta
boost::container::flat_map<u64, CNMT> meta;
std::map<u64, CNMT> meta;
// maps tid -> meta for CNMT in yuzu_meta
boost::container::flat_map<u64, CNMT> yuzu_meta;
std::map<u64, CNMT> yuzu_meta;
};
// Combines multiple RegisteredCaches (i.e. SysNAND, UserNAND, SDMC) into one interface.
class RegisteredCacheUnion {
enum class ContentProviderUnionSlot {
SysNAND, ///< System NAND
UserNAND, ///< User NAND
SDMC, ///< SD Card
FrontendManual, ///< Frontend-defined game list or similar
};
// Combines multiple ContentProvider(s) (i.e. SysNAND, UserNAND, SDMC) into one interface.
class ContentProviderUnion : public ContentProvider {
public:
explicit RegisteredCacheUnion(std::vector<RegisteredCache*> caches);
~ContentProviderUnion() override;
void Refresh();
void SetSlot(ContentProviderUnionSlot slot, ContentProvider* provider);
void ClearSlot(ContentProviderUnionSlot slot);
bool HasEntry(u64 title_id, ContentRecordType type) const;
bool HasEntry(RegisteredCacheEntry entry) const;
void Refresh() override;
bool HasEntry(u64 title_id, ContentRecordType type) const override;
std::optional<u32> GetEntryVersion(u64 title_id) const override;
VirtualFile GetEntryUnparsed(u64 title_id, ContentRecordType type) const override;
VirtualFile GetEntryRaw(u64 title_id, ContentRecordType type) const override;
std::unique_ptr<NCA> GetEntry(u64 title_id, ContentRecordType type) const override;
std::vector<ContentProviderEntry> ListEntriesFilter(
std::optional<TitleType> title_type, std::optional<ContentRecordType> record_type,
std::optional<u64> title_id) const override;
std::optional<u32> GetEntryVersion(u64 title_id) const;
VirtualFile GetEntryUnparsed(u64 title_id, ContentRecordType type) const;
VirtualFile GetEntryUnparsed(RegisteredCacheEntry entry) const;
VirtualFile GetEntryRaw(u64 title_id, ContentRecordType type) const;
VirtualFile GetEntryRaw(RegisteredCacheEntry entry) const;
std::unique_ptr<NCA> GetEntry(u64 title_id, ContentRecordType type) const;
std::unique_ptr<NCA> GetEntry(RegisteredCacheEntry entry) const;
std::vector<RegisteredCacheEntry> ListEntries() const;
// If a parameter is not std::nullopt, it will be filtered for from all entries.
std::vector<RegisteredCacheEntry> ListEntriesFilter(
std::vector<std::pair<ContentProviderUnionSlot, ContentProviderEntry>> ListEntriesFilterOrigin(
std::optional<ContentProviderUnionSlot> origin = {},
std::optional<TitleType> title_type = {}, std::optional<ContentRecordType> record_type = {},
std::optional<u64> title_id = {}) const;
private:
std::vector<RegisteredCache*> caches;
std::map<ContentProviderUnionSlot, ContentProvider*> providers;
};
class ManualContentProvider : public ContentProvider {
public:
~ManualContentProvider() override;
void AddEntry(TitleType title_type, ContentRecordType content_type, u64 title_id,
VirtualFile file);
void ClearAllEntries();
void Refresh() override;
bool HasEntry(u64 title_id, ContentRecordType type) const override;
std::optional<u32> GetEntryVersion(u64 title_id) const override;
VirtualFile GetEntryUnparsed(u64 title_id, ContentRecordType type) const override;
VirtualFile GetEntryRaw(u64 title_id, ContentRecordType type) const override;
std::unique_ptr<NCA> GetEntry(u64 title_id, ContentRecordType type) const override;
std::vector<ContentProviderEntry> ListEntriesFilter(
std::optional<TitleType> title_type, std::optional<ContentRecordType> record_type,
std::optional<u64> title_id) const override;
private:
std::map<std::tuple<TitleType, ContentRecordType, u64>, VirtualFile> entries;
};
} // namespace FileSys

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 = Core::System::GetInstance().GetContentProvider().GetEntry(title_id, type);
break;
case StorageId::NandSystem:
res = Service::FileSystem::GetSystemNANDContents()->GetEntry(title_id, type);

View File

@@ -143,11 +143,12 @@ std::multimap<u64, std::shared_ptr<NCA>> NSP::GetNCAsByTitleID() const {
return out;
}
std::map<u64, std::map<ContentRecordType, std::shared_ptr<NCA>>> NSP::GetNCAs() const {
std::map<u64, std::map<std::pair<TitleType, ContentRecordType>, std::shared_ptr<NCA>>>
NSP::GetNCAs() const {
return ncas;
}
std::shared_ptr<NCA> NSP::GetNCA(u64 title_id, ContentRecordType type) const {
std::shared_ptr<NCA> NSP::GetNCA(u64 title_id, ContentRecordType type, TitleType title_type) const {
if (extracted)
LOG_WARNING(Service_FS, "called on an NSP that is of type extracted.");
@@ -155,14 +156,14 @@ std::shared_ptr<NCA> NSP::GetNCA(u64 title_id, ContentRecordType type) const {
if (title_id_iter == ncas.end())
return nullptr;
const auto type_iter = title_id_iter->second.find(type);
const auto type_iter = title_id_iter->second.find({title_type, type});
if (type_iter == title_id_iter->second.end())
return nullptr;
return type_iter->second;
}
VirtualFile NSP::GetNCAFile(u64 title_id, ContentRecordType type) const {
VirtualFile NSP::GetNCAFile(u64 title_id, ContentRecordType type, TitleType title_type) const {
if (extracted)
LOG_WARNING(Service_FS, "called on an NSP that is of type extracted.");
const auto nca = GetNCA(title_id, type);
@@ -240,7 +241,7 @@ void NSP::ReadNCAs(const std::vector<VirtualFile>& files) {
const CNMT cnmt(inner_file);
auto& ncas_title = ncas[cnmt.GetTitleID()];
ncas_title[ContentRecordType::Meta] = nca;
ncas_title[{cnmt.GetType(), ContentRecordType::Meta}] = nca;
for (const auto& rec : cnmt.GetContentRecords()) {
const auto id_string = Common::HexArrayToString(rec.nca_id, false);
const auto next_file = pfs->GetFile(fmt::format("{}.nca", id_string));
@@ -258,7 +259,7 @@ void NSP::ReadNCAs(const std::vector<VirtualFile>& files) {
if (next_nca->GetStatus() == Loader::ResultStatus::Success ||
(next_nca->GetStatus() == Loader::ResultStatus::ErrorMissingBKTRBaseRomFS &&
(cnmt.GetTitleID() & 0x800) != 0)) {
ncas_title[rec.type] = std::move(next_nca);
ncas_title[{cnmt.GetType(), rec.type}] = std::move(next_nca);
}
}

View File

@@ -42,9 +42,12 @@ public:
// Type 0 Only (Collection of NCAs + Certificate + Ticket + Meta XML)
std::vector<std::shared_ptr<NCA>> GetNCAsCollapsed() const;
std::multimap<u64, std::shared_ptr<NCA>> GetNCAsByTitleID() const;
std::map<u64, std::map<ContentRecordType, std::shared_ptr<NCA>>> GetNCAs() const;
std::shared_ptr<NCA> GetNCA(u64 title_id, ContentRecordType type) const;
VirtualFile GetNCAFile(u64 title_id, ContentRecordType type) const;
std::map<u64, std::map<std::pair<TitleType, ContentRecordType>, std::shared_ptr<NCA>>> GetNCAs()
const;
std::shared_ptr<NCA> GetNCA(u64 title_id, ContentRecordType type,
TitleType title_type = TitleType::Application) const;
VirtualFile GetNCAFile(u64 title_id, ContentRecordType type,
TitleType title_type = TitleType::Application) const;
std::vector<Core::Crypto::Key128> GetTitlekey() const;
std::vector<VirtualFile> GetFiles() const override;
@@ -67,7 +70,7 @@ private:
std::shared_ptr<PartitionFilesystem> pfs;
// Map title id -> {map type -> NCA}
std::map<u64, std::map<ContentRecordType, std::shared_ptr<NCA>>> ncas;
std::map<u64, std::map<std::pair<TitleType, ContentRecordType>, std::shared_ptr<NCA>>> ncas;
std::vector<VirtualFile> ticket_files;
Core::Crypto::KeyManager keys;

View File

@@ -1030,7 +1030,7 @@ static void Step() {
/// Tell the CPU if we hit a memory breakpoint.
bool IsMemoryBreak() {
if (IsConnected()) {
if (!IsConnected()) {
return false;
}

View File

@@ -139,10 +139,8 @@ public:
context->AddDomainObject(std::move(iface));
} else {
auto& kernel = Core::System::GetInstance().Kernel();
auto sessions =
auto [server, client] =
Kernel::ServerSession::CreateSessionPair(kernel, iface->GetServiceName());
auto server = std::get<Kernel::SharedPtr<Kernel::ServerSession>>(sessions);
auto client = std::get<Kernel::SharedPtr<Kernel::ClientSession>>(sessions);
iface->ClientConnected(server);
context->AddMoveObject(std::move(client));
}

View File

@@ -2,8 +2,6 @@
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#include <tuple>
#include "core/hle/kernel/client_port.h"
#include "core/hle/kernel/client_session.h"
#include "core/hle/kernel/errors.h"
@@ -31,18 +29,18 @@ ResultVal<SharedPtr<ClientSession>> ClientPort::Connect() {
active_sessions++;
// Create a new session pair, let the created sessions inherit the parent port's HLE handler.
auto sessions = ServerSession::CreateSessionPair(kernel, server_port->GetName(), this);
auto [server, client] = ServerSession::CreateSessionPair(kernel, server_port->GetName(), this);
if (server_port->HasHLEHandler()) {
server_port->GetHLEHandler()->ClientConnected(std::get<SharedPtr<ServerSession>>(sessions));
server_port->GetHLEHandler()->ClientConnected(server);
} else {
server_port->AppendPendingSession(std::get<SharedPtr<ServerSession>>(sessions));
server_port->AppendPendingSession(server);
}
// Wake the threads waiting on the ServerPort
server_port->WakeupAllWaitingThreads();
return MakeResult(std::get<SharedPtr<ClientSession>>(sessions));
return MakeResult(client);
}
void ClientPort::ConnectionClosed() {

View File

@@ -21,6 +21,7 @@
#include "core/hle/kernel/thread.h"
#include "core/hle/lock.h"
#include "core/hle/result.h"
#include "core/memory.h"
namespace Kernel {
@@ -181,6 +182,7 @@ void KernelCore::AppendNewProcess(SharedPtr<Process> process) {
void KernelCore::MakeCurrentProcess(Process* process) {
impl->current_process = process;
Memory::SetCurrentPageTable(&process->VMManager().page_table);
}
Process* KernelCore::CurrentProcess() {

View File

@@ -32,9 +32,6 @@ namespace {
* @param priority The priority to give the main thread
*/
void SetupMainThread(Process& owner_process, KernelCore& kernel, VAddr entry_point, u32 priority) {
// Setup page table so we can write to memory
Memory::SetCurrentPageTable(&owner_process.VMManager().page_table);
// Initialize new "main" thread
const VAddr stack_top = owner_process.VMManager().GetTLSIORegionEndAddress();
auto thread_res = Thread::Create(kernel, "main", entry_point, priority, 0,
@@ -109,6 +106,8 @@ ResultCode Process::LoadFromMetadata(const FileSys::ProgramMetadata& metadata) {
is_64bit_process = metadata.Is64BitProgram();
vm_manager.Reset(metadata.GetAddressSpaceType());
// Ensure that the potentially resized page table is seen by CPU backends.
Memory::SetCurrentPageTable(&vm_manager.page_table);
const auto& caps = metadata.GetKernelCapabilities();
const auto capability_init_result =

View File

@@ -101,7 +101,6 @@ void Scheduler::SwitchContext(Thread* new_thread) {
auto* const thread_owner_process = current_thread->GetOwnerProcess();
if (previous_process != thread_owner_process) {
system.Kernel().MakeCurrentProcess(thread_owner_process);
Memory::SetCurrentPageTable(&thread_owner_process->VMManager().page_table);
}
cpu_core.LoadContext(new_thread->GetContext());

View File

@@ -39,9 +39,8 @@ void ServerPort::Acquire(Thread* thread) {
ASSERT_MSG(!ShouldWait(thread), "object unavailable!");
}
std::tuple<SharedPtr<ServerPort>, SharedPtr<ClientPort>> ServerPort::CreatePortPair(
KernelCore& kernel, u32 max_sessions, std::string name) {
ServerPort::PortPair ServerPort::CreatePortPair(KernelCore& kernel, u32 max_sessions,
std::string name) {
SharedPtr<ServerPort> server_port(new ServerPort(kernel));
SharedPtr<ClientPort> client_port(new ClientPort(kernel));
@@ -51,7 +50,7 @@ std::tuple<SharedPtr<ServerPort>, SharedPtr<ClientPort>> ServerPort::CreatePortP
client_port->max_sessions = max_sessions;
client_port->active_sessions = 0;
return std::make_tuple(std::move(server_port), std::move(client_port));
return std::make_pair(std::move(server_port), std::move(client_port));
}
} // namespace Kernel

View File

@@ -6,7 +6,7 @@
#include <memory>
#include <string>
#include <tuple>
#include <utility>
#include <vector>
#include "common/common_types.h"
#include "core/hle/kernel/object.h"
@@ -23,6 +23,7 @@ class SessionRequestHandler;
class ServerPort final : public WaitObject {
public:
using HLEHandler = std::shared_ptr<SessionRequestHandler>;
using PortPair = std::pair<SharedPtr<ServerPort>, SharedPtr<ClientPort>>;
/**
* Creates a pair of ServerPort and an associated ClientPort.
@@ -32,8 +33,8 @@ public:
* @param name Optional name of the ports
* @return The created port tuple
*/
static std::tuple<SharedPtr<ServerPort>, SharedPtr<ClientPort>> CreatePortPair(
KernelCore& kernel, u32 max_sessions, std::string name = "UnknownPort");
static PortPair CreatePortPair(KernelCore& kernel, u32 max_sessions,
std::string name = "UnknownPort");
std::string GetTypeName() const override {
return "ServerPort";

View File

@@ -204,6 +204,6 @@ ServerSession::SessionPair ServerSession::CreateSessionPair(KernelCore& kernel,
client_session->parent = parent;
server_session->parent = parent;
return std::make_tuple(std::move(server_session), std::move(client_session));
return std::make_pair(std::move(server_session), std::move(client_session));
}
} // namespace Kernel

View File

@@ -6,6 +6,7 @@
#include <memory>
#include <string>
#include <utility>
#include <vector>
#include "core/hle/kernel/object.h"
@@ -41,6 +42,10 @@ public:
return "ServerSession";
}
std::string GetName() const override {
return name;
}
static const HandleType HANDLE_TYPE = HandleType::ServerSession;
HandleType GetHandleType() const override {
return HANDLE_TYPE;
@@ -54,7 +59,7 @@ public:
return parent.get();
}
using SessionPair = std::tuple<SharedPtr<ServerSession>, SharedPtr<ClientSession>>;
using SessionPair = std::pair<SharedPtr<ServerSession>, SharedPtr<ClientSession>>;
/**
* Creates a pair of ServerSession and an associated ClientSession.

View File

@@ -1339,6 +1339,20 @@ static ResultCode WaitProcessWideKeyAtomic(VAddr mutex_addr, VAddr condition_var
"called mutex_addr={:X}, condition_variable_addr={:X}, thread_handle=0x{:08X}, timeout={}",
mutex_addr, condition_variable_addr, thread_handle, nano_seconds);
if (Memory::IsKernelVirtualAddress(mutex_addr)) {
LOG_ERROR(
Kernel_SVC,
"Given mutex address must not be within the kernel address space. address=0x{:016X}",
mutex_addr);
return ERR_INVALID_ADDRESS_STATE;
}
if (!Common::IsWordAligned(mutex_addr)) {
LOG_ERROR(Kernel_SVC, "Given mutex address must be word-aligned. address=0x{:016X}",
mutex_addr);
return ERR_INVALID_ADDRESS;
}
auto* const current_process = Core::System::GetInstance().Kernel().CurrentProcess();
const auto& handle_table = current_process->GetHandleTable();
SharedPtr<Thread> thread = handle_table.Get<Thread>(thread_handle);

View File

@@ -119,10 +119,6 @@ union ResultCode {
BitField<0, 9, ErrorModule> module;
BitField<9, 13, u32> description;
// The last bit of `level` is checked by apps and the kernel to determine if a result code is an
// error
BitField<31, 1, u32> is_error;
constexpr explicit ResultCode(u32 raw) : raw(raw) {}
constexpr ResultCode(ErrorModule module_, u32 description_)

View File

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

View File

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

View File

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

View File

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

View File

@@ -224,6 +224,7 @@ IDebugFunctions::IDebugFunctions() : ServiceFramework{"IDebugFunctions"} {
{20, nullptr, "InvalidateTransitionLayer"},
{30, nullptr, "RequestLaunchApplicationWithUserAndArgumentForDebug"},
{40, nullptr, "GetAppletResourceUsageInfo"},
{41, nullptr, "SetCpuBoostModeForApplet"},
};
// clang-format on
@@ -256,6 +257,7 @@ ISelfController::ISelfController(std::shared_ptr<NVFlinger::NVFlinger> nvflinger
{40, &ISelfController::CreateManagedDisplayLayer, "CreateManagedDisplayLayer"},
{41, nullptr, "IsSystemBufferSharingEnabled"},
{42, nullptr, "GetSystemSharedLayerHandle"},
{43, nullptr, "GetSystemSharedBufferHandle"},
{50, &ISelfController::SetHandlesRequestToDisplay, "SetHandlesRequestToDisplay"},
{51, nullptr, "ApproveToDisplay"},
{60, nullptr, "OverrideAutoSleepTimeAndDimmingTime"},
@@ -269,9 +271,11 @@ ISelfController::ISelfController(std::shared_ptr<NVFlinger::NVFlinger> nvflinger
{68, nullptr, "SetAutoSleepDisabled"},
{69, nullptr, "IsAutoSleepDisabled"},
{70, nullptr, "ReportMultimediaError"},
{71, nullptr, "GetCurrentIlluminanceEx"},
{80, nullptr, "SetWirelessPriorityMode"},
{90, nullptr, "GetAccumulatedSuspendedTickValue"},
{91, nullptr, "GetAccumulatedSuspendedTickChangedEvent"},
{100, nullptr, "SetAlbumImageTakenNotificationEnabled"},
{1000, nullptr, "GetDebugStorageChannel"},
};
// clang-format on
@@ -363,8 +367,6 @@ void ISelfController::SetPerformanceModeChangedNotification(Kernel::HLERequestCo
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};
struct FocusHandlingModeParams {
@@ -372,7 +374,10 @@ void ISelfController::SetFocusHandlingMode(Kernel::HLERequestContext& ctx) {
u8 unknown1;
u8 unknown2;
};
auto flags = rp.PopRaw<FocusHandlingModeParams>();
const auto flags = rp.PopRaw<FocusHandlingModeParams>();
LOG_WARNING(Service_AM, "(STUBBED) called. unknown0={}, unknown1={}, unknown2={}",
flags.unknown0, flags.unknown1, flags.unknown2);
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS);
@@ -515,11 +520,20 @@ ICommonStateGetter::ICommonStateGetter(std::shared_ptr<AppletMessageQueue> msg_q
{50, nullptr, "IsVrModeEnabled"},
{51, nullptr, "SetVrModeEnabled"},
{52, nullptr, "SwitchLcdBacklight"},
{53, nullptr, "BeginVrModeEx"},
{54, nullptr, "EndVrModeEx"},
{55, nullptr, "IsInControllerFirmwareUpdateSection"},
{60, &ICommonStateGetter::GetDefaultDisplayResolution, "GetDefaultDisplayResolution"},
{61, &ICommonStateGetter::GetDefaultDisplayResolutionChangeEvent, "GetDefaultDisplayResolutionChangeEvent"},
{62, nullptr, "GetHdcpAuthenticationState"},
{63, nullptr, "GetHdcpAuthenticationStateChangeEvent"},
{64, nullptr, "SetTvPowerStateMatchingMode"},
{65, nullptr, "GetApplicationIdByContentActionName"},
{66, nullptr, "SetCpuBoostMode"},
{80, nullptr, "PerformSystemButtonPressingIfInFocus"},
{90, nullptr, "SetPerformanceConfigurationChangedNotification"},
{91, nullptr, "GetCurrentPerformanceConfiguration"},
{200, nullptr, "GetOperationModeSystemInfo"},
};
// clang-format on
@@ -959,6 +973,8 @@ IApplicationFunctions::IApplicationFunctions() : ServiceFramework("IApplicationF
{11, nullptr, "CreateApplicationAndPushAndRequestToStartForQuest"},
{12, nullptr, "CreateApplicationAndRequestToStart"},
{13, &IApplicationFunctions::CreateApplicationAndRequestToStartForQuest, "CreateApplicationAndRequestToStartForQuest"},
{14, nullptr, "CreateApplicationWithAttributeAndPushAndRequestToStartForQuest"},
{15, nullptr, "CreateApplicationWithAttributeAndRequestToStartForQuest"},
{20, &IApplicationFunctions::EnsureSaveData, "EnsureSaveData"},
{21, &IApplicationFunctions::GetDesiredLanguage, "GetDesiredLanguage"},
{22, &IApplicationFunctions::SetTerminateResult, "SetTerminateResult"},
@@ -1232,6 +1248,7 @@ IGlobalStateController::IGlobalStateController() : ServiceFramework("IGlobalStat
{2, nullptr, "StartSleepSequence"},
{3, nullptr, "StartShutdownSequence"},
{4, nullptr, "StartRebootSequence"},
{9, nullptr, "IsAutoPowerDownRequested"},
{10, nullptr, "LoadAndApplyIdlePolicySettings"},
{11, nullptr, "NotifyCecSettingsChanged"},
{12, nullptr, "SetDefaultHomeButtonLongPressTime"},

View File

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

View File

@@ -86,7 +86,7 @@ static FileSys::VirtualFile GetManualRomFS() {
if (loader.ReadManualRomFS(out) == Loader::ResultStatus::Success)
return out;
const auto& installed{FileSystem::GetUnionContents()};
const auto& installed{Core::System::GetInstance().GetContentProvider()};
const auto res = installed.GetEntry(Core::System::GetInstance().CurrentProcess()->GetTitleID(),
FileSys::ContentRecordType::Manual);

View File

@@ -33,11 +33,11 @@ static bool CheckAOCTitleIDMatchesBase(u64 title_id, u64 base) {
static std::vector<u64> AccumulateAOCTitleIDs() {
std::vector<u64> add_on_content;
const auto rcu = FileSystem::GetUnionContents();
const auto& rcu = Core::System::GetInstance().GetContentProvider();
const auto list =
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; });
[](const FileSys::ContentProviderEntry& rce) { return rce.title_id; });
add_on_content.erase(
std::remove_if(
add_on_content.begin(), add_on_content.end(),
@@ -50,6 +50,7 @@ static std::vector<u64> AccumulateAOCTitleIDs() {
}
AOC_U::AOC_U() : ServiceFramework("aoc:u"), add_on_content(AccumulateAOCTitleIDs()) {
// clang-format off
static const FunctionInfo functions[] = {
{0, nullptr, "CountAddOnContentByApplicationId"},
{1, nullptr, "ListAddOnContentByApplicationId"},
@@ -60,7 +61,10 @@ AOC_U::AOC_U() : ServiceFramework("aoc:u"), add_on_content(AccumulateAOCTitleIDs
{6, nullptr, "PrepareAddOnContentByApplicationId"},
{7, &AOC_U::PrepareAddOnContent, "PrepareAddOnContent"},
{8, &AOC_U::GetAddOnContentListChangedEvent, "GetAddOnContentListChangedEvent"},
{100, nullptr, "CreateEcPurchasedEventManager"},
};
// clang-format on
RegisterHandlers(functions);
auto& kernel = Core::System::GetInstance().Kernel();

View File

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

View File

@@ -2,9 +2,6 @@
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#include "common/logging/log.h"
#include "core/hle/ipc_helpers.h"
#include "core/hle/kernel/hle_ipc.h"
#include "core/hle/service/audio/audin_u.h"
namespace Service::Audio {
@@ -28,12 +25,12 @@ public:
{11, nullptr, "GetAudioInBufferCount"},
{12, nullptr, "SetAudioInDeviceGain"},
{13, nullptr, "GetAudioInDeviceGain"},
{14, nullptr, "FlushAudioInBuffers"},
};
// clang-format on
RegisterHandlers(functions);
}
~IAudioIn() = default;
};
AudInU::AudInU() : ServiceFramework("audin:u") {

View File

@@ -44,7 +44,7 @@ public:
std::string&& unique_name)
: ServiceFramework("IAudioOut"), audio_core(audio_core),
device_name(std::move(device_name)), audio_params(audio_params) {
// clang-format off
static const FunctionInfo functions[] = {
{0, &IAudioOut::GetAudioOutState, "GetAudioOutState"},
{1, &IAudioOut::StartAudioOut, "StartAudioOut"},
@@ -58,7 +58,10 @@ public:
{9, &IAudioOut::GetAudioOutBufferCount, "GetAudioOutBufferCount"},
{10, nullptr, "GetAudioOutPlayedSampleCount"},
{11, nullptr, "FlushAudioOutBuffers"},
{12, nullptr, "SetAudioOutVolume"},
{13, nullptr, "GetAudioOutVolume"},
};
// clang-format on
RegisterHandlers(functions);
// This is the event handle used to check if the audio buffer was released
@@ -150,7 +153,6 @@ 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)};
@@ -194,12 +196,9 @@ private:
void AudOutU::ListAudioOutsImpl(Kernel::HLERequestContext& ctx) {
LOG_DEBUG(Service_Audio, "called");
IPC::RequestParser rp{ctx};
ctx.WriteBuffer(DefaultDevice);
IPC::ResponseBuilder rb{ctx, 3};
rb.Push(RESULT_SUCCESS);
rb.Push<u32>(1); // Amount of audio devices
}

View File

@@ -2,9 +2,6 @@
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#include "common/logging/log.h"
#include "core/hle/ipc_helpers.h"
#include "core/hle/kernel/hle_ipc.h"
#include "core/hle/service/audio/audrec_u.h"
namespace Service::Audio {
@@ -30,7 +27,6 @@ public:
RegisterHandlers(functions);
}
~IFinalOutputRecorder() = default;
};
AudRecU::AudRecU() : ServiceFramework("audrec:u") {

View File

@@ -10,6 +10,7 @@
#include "common/alignment.h"
#include "common/common_funcs.h"
#include "common/logging/log.h"
#include "common/string_util.h"
#include "core/core.h"
#include "core/hle/ipc_helpers.h"
#include "core/hle/kernel/hle_ipc.h"
@@ -184,7 +185,6 @@ public:
private:
void ListAudioDeviceName(Kernel::HLERequestContext& ctx) {
LOG_WARNING(Service_Audio, "(STUBBED) called");
IPC::RequestParser rp{ctx};
constexpr std::array<char, 15> audio_interface{{"AudioInterface"}};
ctx.WriteBuffer(audio_interface);
@@ -195,13 +195,13 @@ private:
}
void SetAudioDeviceOutputVolume(Kernel::HLERequestContext& ctx) {
LOG_WARNING(Service_Audio, "(STUBBED) called");
IPC::RequestParser rp{ctx};
f32 volume = static_cast<f32>(rp.Pop<u32>());
const f32 volume = rp.Pop<f32>();
auto file_buffer = ctx.ReadBuffer();
auto end = std::find(file_buffer.begin(), file_buffer.end(), '\0');
const auto device_name_buffer = ctx.ReadBuffer();
const std::string name = Common::StringFromBuffer(device_name_buffer);
LOG_WARNING(Service_Audio, "(STUBBED) called. name={}, volume={}", name, volume);
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS);
@@ -209,7 +209,6 @@ private:
void GetActiveAudioDeviceName(Kernel::HLERequestContext& ctx) {
LOG_WARNING(Service_Audio, "(STUBBED) called");
IPC::RequestParser rp{ctx};
constexpr std::array<char, 12> audio_interface{{"AudioDevice"}};
ctx.WriteBuffer(audio_interface);

View File

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

View File

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

View File

@@ -197,13 +197,16 @@ ResultCode VfsDirectoryServiceWrapper::RenameDirectory(const std::string& src_pa
ResultVal<FileSys::VirtualFile> VfsDirectoryServiceWrapper::OpenFile(const std::string& path_,
FileSys::Mode mode) const {
std::string path(FileUtil::SanitizePath(path_));
auto npath = path;
while (npath.size() > 0 && (npath[0] == '/' || npath[0] == '\\'))
npath = npath.substr(1);
const std::string path(FileUtil::SanitizePath(path_));
std::string_view npath = path;
while (!npath.empty() && (npath[0] == '/' || npath[0] == '\\')) {
npath.remove_prefix(1);
}
auto file = backing->GetFileRelative(npath);
if (file == nullptr)
if (file == nullptr) {
return FileSys::ERROR_PATH_NOT_FOUND;
}
if (mode == FileSys::Mode::Append) {
return MakeResult<FileSys::VirtualFile>(
@@ -388,11 +391,6 @@ void WriteSaveDataSize(FileSys::SaveDataType type, u64 title_id, u128 user_id,
save_data_factory->WriteSaveDataSize(type, title_id, user_id, new_value);
}
FileSys::RegisteredCacheUnion GetUnionContents() {
return FileSys::RegisteredCacheUnion{
{GetSystemNANDContents(), GetUserNANDContents(), GetSDMCContents()}};
}
FileSys::RegisteredCache* GetSystemNANDContents() {
LOG_TRACE(Service_FS, "Opening System NAND Contents");
@@ -457,6 +455,10 @@ void CreateFactories(FileSys::VfsFilesystem& vfs, bool overwrite) {
if (bis_factory == nullptr) {
bis_factory =
std::make_unique<FileSys::BISFactory>(nand_directory, load_directory, dump_directory);
Core::System::GetInstance().RegisterContentProvider(
FileSys::ContentProviderUnionSlot::SysNAND, bis_factory->GetSystemNANDContents());
Core::System::GetInstance().RegisterContentProvider(
FileSys::ContentProviderUnionSlot::UserNAND, bis_factory->GetUserNANDContents());
}
if (save_data_factory == nullptr) {
@@ -465,6 +467,8 @@ void CreateFactories(FileSys::VfsFilesystem& vfs, bool overwrite) {
if (sdmc_factory == nullptr) {
sdmc_factory = std::make_unique<FileSys::SDMCFactory>(std::move(sd_directory));
Core::System::GetInstance().RegisterContentProvider(FileSys::ContentProviderUnionSlot::SDMC,
sdmc_factory->GetSDMCContents());
}
}

View File

@@ -54,8 +54,6 @@ FileSys::SaveDataSize ReadSaveDataSize(FileSys::SaveDataType type, u64 title_id,
void WriteSaveDataSize(FileSys::SaveDataType type, u64 title_id, u128 user_id,
FileSys::SaveDataSize new_value);
FileSys::RegisteredCacheUnion GetUnionContents();
FileSys::RegisteredCache* GetSystemNANDContents();
FileSys::RegisteredCache* GetUserNANDContents();
FileSys::RegisteredCache* GetSDMCContents();

View File

@@ -315,61 +315,53 @@ public:
void CreateFile(Kernel::HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
auto file_buffer = ctx.ReadBuffer();
std::string name = Common::StringFromBuffer(file_buffer);
const auto file_buffer = ctx.ReadBuffer();
const std::string name = Common::StringFromBuffer(file_buffer);
u64 mode = rp.Pop<u64>();
u32 size = rp.Pop<u32>();
const u64 mode = rp.Pop<u64>();
const u32 size = rp.Pop<u32>();
LOG_DEBUG(Service_FS, "called file {} mode 0x{:X} size 0x{:08X}", name, mode, size);
LOG_DEBUG(Service_FS, "called. file={}, mode=0x{:X}, size=0x{:08X}", name, mode, size);
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(backend.CreateFile(name, size));
}
void DeleteFile(Kernel::HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
const auto file_buffer = ctx.ReadBuffer();
const std::string name = Common::StringFromBuffer(file_buffer);
auto file_buffer = ctx.ReadBuffer();
std::string name = Common::StringFromBuffer(file_buffer);
LOG_DEBUG(Service_FS, "called file {}", name);
LOG_DEBUG(Service_FS, "called. file={}", name);
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(backend.DeleteFile(name));
}
void CreateDirectory(Kernel::HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
const auto file_buffer = ctx.ReadBuffer();
const std::string name = Common::StringFromBuffer(file_buffer);
auto file_buffer = ctx.ReadBuffer();
std::string name = Common::StringFromBuffer(file_buffer);
LOG_DEBUG(Service_FS, "called directory {}", name);
LOG_DEBUG(Service_FS, "called. directory={}", name);
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(backend.CreateDirectory(name));
}
void DeleteDirectory(Kernel::HLERequestContext& ctx) {
const IPC::RequestParser rp{ctx};
const auto file_buffer = ctx.ReadBuffer();
std::string name = Common::StringFromBuffer(file_buffer);
const std::string name = Common::StringFromBuffer(file_buffer);
LOG_DEBUG(Service_FS, "called directory {}", name);
LOG_DEBUG(Service_FS, "called. directory={}", name);
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(backend.DeleteDirectory(name));
}
void DeleteDirectoryRecursively(Kernel::HLERequestContext& ctx) {
const IPC::RequestParser rp{ctx};
const auto file_buffer = ctx.ReadBuffer();
std::string name = Common::StringFromBuffer(file_buffer);
const std::string name = Common::StringFromBuffer(file_buffer);
LOG_DEBUG(Service_FS, "called directory {}", name);
LOG_DEBUG(Service_FS, "called. directory={}", name);
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(backend.DeleteDirectoryRecursively(name));
@@ -386,18 +378,16 @@ public:
}
void RenameFile(Kernel::HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
std::vector<u8> buffer;
buffer.resize(ctx.BufferDescriptorX()[0].Size());
Memory::ReadBlock(ctx.BufferDescriptorX()[0].Address(), buffer.data(), buffer.size());
std::string src_name = Common::StringFromBuffer(buffer);
const std::string src_name = Common::StringFromBuffer(buffer);
buffer.resize(ctx.BufferDescriptorX()[1].Size());
Memory::ReadBlock(ctx.BufferDescriptorX()[1].Address(), buffer.data(), buffer.size());
std::string dst_name = Common::StringFromBuffer(buffer);
const std::string dst_name = Common::StringFromBuffer(buffer);
LOG_DEBUG(Service_FS, "called file '{}' to file '{}'", src_name, dst_name);
LOG_DEBUG(Service_FS, "called. file '{}' to file '{}'", src_name, dst_name);
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(backend.RenameFile(src_name, dst_name));
@@ -406,12 +396,12 @@ public:
void OpenFile(Kernel::HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
auto file_buffer = ctx.ReadBuffer();
std::string name = Common::StringFromBuffer(file_buffer);
const auto file_buffer = ctx.ReadBuffer();
const std::string name = Common::StringFromBuffer(file_buffer);
auto mode = static_cast<FileSys::Mode>(rp.Pop<u32>());
const auto mode = static_cast<FileSys::Mode>(rp.Pop<u32>());
LOG_DEBUG(Service_FS, "called file {} mode {}", name, static_cast<u32>(mode));
LOG_DEBUG(Service_FS, "called. file={}, mode={}", name, static_cast<u32>(mode));
auto result = backend.OpenFile(name, mode);
if (result.Failed()) {
@@ -430,13 +420,13 @@ public:
void OpenDirectory(Kernel::HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
auto file_buffer = ctx.ReadBuffer();
std::string name = Common::StringFromBuffer(file_buffer);
const auto file_buffer = ctx.ReadBuffer();
const std::string name = Common::StringFromBuffer(file_buffer);
// TODO(Subv): Implement this filter.
u32 filter_flags = rp.Pop<u32>();
const u32 filter_flags = rp.Pop<u32>();
LOG_DEBUG(Service_FS, "called directory {} filter {}", name, filter_flags);
LOG_DEBUG(Service_FS, "called. directory={}, filter={}", name, filter_flags);
auto result = backend.OpenDirectory(name);
if (result.Failed()) {
@@ -453,12 +443,10 @@ public:
}
void GetEntryType(Kernel::HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
const auto file_buffer = ctx.ReadBuffer();
const std::string name = Common::StringFromBuffer(file_buffer);
auto file_buffer = ctx.ReadBuffer();
std::string name = Common::StringFromBuffer(file_buffer);
LOG_DEBUG(Service_FS, "called file {}", name);
LOG_DEBUG(Service_FS, "called. file={}", name);
auto result = backend.GetEntryType(name);
if (result.Failed()) {
@@ -677,10 +665,13 @@ FSP_SRV::FSP_SRV() : ServiceFramework("fsp-srv") {
{100, nullptr, "OpenImageDirectoryFileSystem"},
{110, nullptr, "OpenContentStorageFileSystem"},
{120, nullptr, "OpenCloudBackupWorkStorageFileSystem"},
{130, nullptr, "OpenCustomStorageFileSystem"},
{200, &FSP_SRV::OpenDataStorageByCurrentProcess, "OpenDataStorageByCurrentProcess"},
{201, nullptr, "OpenDataStorageByProgramId"},
{202, &FSP_SRV::OpenDataStorageByDataId, "OpenDataStorageByDataId"},
{203, &FSP_SRV::OpenPatchDataStorageByCurrentProcess, "OpenPatchDataStorageByCurrentProcess"},
{204, nullptr, "OpenDataFileSystemByProgramIndex"},
{205, nullptr, "OpenDataStorageByProgramIndex"},
{400, nullptr, "OpenDeviceOperator"},
{500, nullptr, "OpenSdCardDetectionEventNotifier"},
{501, nullptr, "OpenGameCardDetectionEventNotifier"},
@@ -704,6 +695,7 @@ FSP_SRV::FSP_SRV() : ServiceFramework("fsp-srv") {
{614, nullptr, "CorruptSaveDataFileSystemBySaveDataSpaceId"},
{615, nullptr, "QuerySaveDataInternalStorageTotalSize"},
{616, nullptr, "GetSaveDataCommitId"},
{617, nullptr, "UnregisterExternalKey"},
{620, nullptr, "SetSdCardEncryptionSeed"},
{630, nullptr, "SetSdCardAccessibility"},
{631, nullptr, "IsSdCardAccessible"},
@@ -714,6 +706,7 @@ FSP_SRV::FSP_SRV() : ServiceFramework("fsp-srv") {
{710, nullptr, "ResolveAccessFailure"},
{720, nullptr, "AbandonAccessFailure"},
{800, nullptr, "GetAndClearFileSystemProxyErrorInfo"},
{810, nullptr, "RegisterProgramIndexMapInfo"},
{1000, nullptr, "SetBisRootForHost"},
{1001, nullptr, "SetSaveDataSize"},
{1002, nullptr, "SetSaveDataRootPath"},
@@ -724,6 +717,8 @@ FSP_SRV::FSP_SRV() : ServiceFramework("fsp-srv") {
{1007, nullptr, "RegisterUpdatePartition"},
{1008, nullptr, "OpenRegisteredUpdatePartition"},
{1009, nullptr, "GetAndClearMemoryReportInfo"},
{1010, nullptr, "SetDataStorageRedirectTarget"},
{1011, nullptr, "OutputAccessLogToSdCard2"},
{1100, nullptr, "OverrideSaveDataTransferTokenSignVerificationKey"},
{1110, nullptr, "CorruptSaveDataFileSystemBySaveDataSpaceId2"},
{1200, nullptr, "OpenMultiCommitManager"},

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -18,7 +18,7 @@ class nvmap;
class nvdisp_disp0 final : public nvdevice {
public:
explicit nvdisp_disp0(std::shared_ptr<nvmap> nvmap_dev);
~nvdisp_disp0();
~nvdisp_disp0() override;
u32 ioctl(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output) override;

View File

@@ -17,7 +17,7 @@ namespace Service::Nvidia {
class NVDRV final : public ServiceFramework<NVDRV> {
public:
NVDRV(std::shared_ptr<Module> nvdrv, const char* name);
~NVDRV();
~NVDRV() override;
private:
void Open(Kernel::HLERequestContext& ctx);

View File

@@ -11,7 +11,7 @@ namespace Service::Nvidia {
class NVMEMP final : public ServiceFramework<NVMEMP> {
public:
NVMEMP();
~NVMEMP();
~NVMEMP() override;
private:
void Cmd0(Kernel::HLERequestContext& ctx);

View File

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

View File

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

View File

@@ -90,7 +90,7 @@ private:
Kernel::HLERequestContext& ctx);
ServiceFrameworkBase(const char* service_name, u32 max_sessions, InvokerFn* handler_invoker);
~ServiceFrameworkBase();
~ServiceFrameworkBase() override;
void RegisterHandlersBase(const FunctionInfoBase* functions, std::size_t n);
void ReportUnimplementedFunction(Kernel::HLERequestContext& ctx, const FunctionInfoBase* info);

View File

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

View File

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

View File

@@ -11,7 +11,7 @@ namespace Service::Set {
class SET_CAL final : public ServiceFramework<SET_CAL> {
public:
explicit SET_CAL();
~SET_CAL();
~SET_CAL() override;
};
} // namespace Service::Set

View File

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

View File

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

View File

@@ -8,12 +8,20 @@
namespace Service::Sockets {
void SFDNSRES::GetAddrInfo(Kernel::HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
struct Parameters {
u8 use_nsd_resolve;
u32 unknown;
u64 process_id;
};
LOG_WARNING(Service, "(STUBBED) called");
IPC::RequestParser rp{ctx};
const auto parameters = rp.PopRaw<Parameters>();
LOG_WARNING(Service,
"(STUBBED) called. use_nsd_resolve={}, unknown=0x{:08X}, process_id=0x{:016X}",
parameters.use_nsd_resolve, parameters.unknown, parameters.process_id);
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS);
}

View File

@@ -26,9 +26,7 @@ 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();
const std::size_t size = ctx.GetWriteBufferSize();
std::uniform_int_distribution<u16> distribution(0, std::numeric_limits<u8>::max());
std::vector<u8> data(size);

View File

@@ -64,13 +64,19 @@ public:
};
RegisterHandlers(functions);
}
~ISslContext() = default;
private:
void SetOption(Kernel::HLERequestContext& ctx) {
LOG_WARNING(Service_SSL, "(STUBBED) called");
struct Parameters {
u8 enable;
u32 option;
};
IPC::RequestParser rp{ctx};
const auto parameters = rp.PopRaw<Parameters>();
LOG_WARNING(Service_SSL, "(STUBBED) called. enable={}, option={}", parameters.enable,
parameters.option);
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS);
@@ -97,6 +103,8 @@ public:
{4, nullptr, "DebugIoctl"},
{5, &SSL::SetInterfaceVersion, "SetInterfaceVersion"},
{6, nullptr, "FlushSessionCache"},
{7, nullptr, "SetDebugOption"},
{8, nullptr, "GetDebugOption"},
};
// clang-format on

View File

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

View File

@@ -498,7 +498,6 @@ public:
};
RegisterHandlers(functions);
}
~IHOSBinderDriver() = default;
private:
enum class TransactionId {
@@ -692,7 +691,6 @@ public:
};
RegisterHandlers(functions);
}
~ISystemDisplayService() = default;
private:
void SetLayerZ(Kernel::HLERequestContext& ctx) {
@@ -818,7 +816,6 @@ public:
};
RegisterHandlers(functions);
}
~IManagerDisplayService() = default;
private:
void CloseDisplay(Kernel::HLERequestContext& ctx) {
@@ -884,7 +881,6 @@ private:
class IApplicationDisplayService final : public ServiceFramework<IApplicationDisplayService> {
public:
explicit IApplicationDisplayService(std::shared_ptr<NVFlinger::NVFlinger> nv_flinger);
~IApplicationDisplayService() = default;
private:
enum class ConvertedScaleMode : u64 {
@@ -1037,7 +1033,6 @@ 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);
display_info.height *= static_cast<u64>(Settings::values.resolution_factor);

View File

@@ -21,6 +21,8 @@
#include "core/memory.h"
#include "core/settings.h"
#pragma optimize("", off)
namespace Loader {
namespace {
struct MODHeader {
@@ -136,13 +138,13 @@ std::optional<VAddr> AppLoader_NSO::LoadModule(Kernel::Process& process,
// Apply patches if necessary
if (pm && (pm->HasNSOPatch(nso_header.build_id) || Settings::values.dump_nso)) {
std::vector<u8> pi_header(sizeof(NSOHeader) + program_image.size());
std::vector<u8> pi_header;
pi_header.insert(pi_header.begin(), reinterpret_cast<u8*>(&nso_header),
reinterpret_cast<u8*>(&nso_header) + sizeof(NSOHeader));
pi_header.insert(pi_header.begin() + sizeof(NSOHeader), program_image.begin(),
program_image.end());
pi_header = pm->PatchNSO(pi_header);
pi_header = pm->PatchNSO(pi_header, file.GetName());
std::copy(pi_header.begin() + sizeof(NSOHeader), pi_header.end(), program_image.begin());
}

View File

@@ -22,7 +22,7 @@ class AppLoader_NCA;
class AppLoader_XCI final : public AppLoader {
public:
explicit AppLoader_XCI(FileSys::VirtualFile file);
~AppLoader_XCI();
~AppLoader_XCI() override;
/**
* Returns the type of the file

View File

@@ -38,10 +38,6 @@ void SetCurrentPageTable(Common::PageTable* page_table) {
}
}
Common::PageTable* GetCurrentPageTable() {
return current_page_table;
}
static void MapPages(Common::PageTable& page_table, VAddr base, u64 size, u8* memory,
Common::PageType type) {
LOG_DEBUG(HW_Memory, "Mapping {} onto {:016X}-{:016X}", fmt::ptr(memory), base * PAGE_SIZE,

View File

@@ -28,16 +28,6 @@ constexpr u64 PAGE_MASK = PAGE_SIZE - 1;
/// Virtual user-space memory regions
enum : VAddr {
/// Read-only page containing kernel and system configuration values.
CONFIG_MEMORY_VADDR = 0x1FF80000,
CONFIG_MEMORY_SIZE = 0x00001000,
CONFIG_MEMORY_VADDR_END = CONFIG_MEMORY_VADDR + CONFIG_MEMORY_SIZE,
/// Usually read-only page containing mostly values read from hardware.
SHARED_PAGE_VADDR = 0x1FF81000,
SHARED_PAGE_SIZE = 0x00001000,
SHARED_PAGE_VADDR_END = SHARED_PAGE_VADDR + SHARED_PAGE_SIZE,
/// TLS (Thread-Local Storage) related.
TLS_ENTRY_SIZE = 0x200,
@@ -50,9 +40,8 @@ enum : VAddr {
KERNEL_REGION_END = KERNEL_REGION_VADDR + KERNEL_REGION_SIZE,
};
/// Currently active page table
/// Changes the currently active page table.
void SetCurrentPageTable(Common::PageTable* page_table);
Common::PageTable* GetCurrentPageTable();
/// Determines if the given VAddr is valid for the specified process.
bool IsValidVirtualAddress(const Kernel::Process& process, VAddr vaddr);

View File

@@ -17,7 +17,6 @@ TestEnvironment::TestEnvironment(bool mutable_memory_)
: mutable_memory(mutable_memory_),
test_memory(std::make_shared<TestMemory>(this)), kernel{Core::System::GetInstance()} {
auto process = Kernel::Process::Create(Core::System::GetInstance(), "");
kernel.MakeCurrentProcess(process.get());
page_table = &process->VMManager().page_table;
std::fill(page_table->pointers.begin(), page_table->pointers.end(), nullptr);
@@ -28,7 +27,7 @@ TestEnvironment::TestEnvironment(bool mutable_memory_)
Memory::MapIoRegion(*page_table, 0x00000000, 0x80000000, test_memory);
Memory::MapIoRegion(*page_table, 0x80000000, 0x80000000, test_memory);
Memory::SetCurrentPageTable(page_table);
kernel.MakeCurrentProcess(process.get());
}
TestEnvironment::~TestEnvironment() {

View File

@@ -8,6 +8,7 @@
#include "video_core/dma_pusher.h"
#include "video_core/engines/maxwell_3d.h"
#include "video_core/gpu.h"
#include "video_core/memory_manager.h"
namespace Tegra {

View File

@@ -6,12 +6,13 @@
#include "common/logging/log.h"
#include "common/math_util.h"
#include "video_core/engines/fermi_2d.h"
#include "video_core/memory_manager.h"
#include "video_core/rasterizer_interface.h"
namespace Tegra::Engines {
Fermi2D::Fermi2D(VideoCore::RasterizerInterface& rasterizer, MemoryManager& memory_manager)
: memory_manager(memory_manager), rasterizer{rasterizer} {}
: rasterizer{rasterizer}, memory_manager{memory_manager} {}
void Fermi2D::CallMethod(const GPU::MethodCall& method_call) {
ASSERT_MSG(method_call.method < Regs::NUM_REGS,

View File

@@ -10,7 +10,10 @@
#include "common/common_funcs.h"
#include "common/common_types.h"
#include "video_core/gpu.h"
#include "video_core/memory_manager.h"
namespace Tegra {
class MemoryManager;
}
namespace VideoCore {
class RasterizerInterface;
@@ -115,10 +118,9 @@ public:
};
} regs{};
MemoryManager& memory_manager;
private:
VideoCore::RasterizerInterface& rasterizer;
MemoryManager& memory_manager;
/// Performs the copy from the source surface to the destination surface as configured in the
/// registers.

View File

@@ -9,7 +9,10 @@
#include "common/common_funcs.h"
#include "common/common_types.h"
#include "video_core/gpu.h"
#include "video_core/memory_manager.h"
namespace Tegra {
class MemoryManager;
}
namespace Tegra::Engines {
@@ -40,10 +43,11 @@ public:
static_assert(sizeof(Regs) == Regs::NUM_REGS * sizeof(u32),
"KeplerCompute Regs has wrong size");
MemoryManager& memory_manager;
/// Write the value to the register identified by method.
void CallMethod(const GPU::MethodCall& method_call);
private:
MemoryManager& memory_manager;
};
#define ASSERT_REG_POSITION(field_name, position) \

View File

@@ -5,9 +5,9 @@
#include "common/assert.h"
#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/memory_manager.h"
#include "video_core/rasterizer_interface.h"
#include "video_core/renderer_base.h"
@@ -15,7 +15,7 @@ namespace Tegra::Engines {
KeplerMemory::KeplerMemory(Core::System& system, VideoCore::RasterizerInterface& rasterizer,
MemoryManager& memory_manager)
: system{system}, memory_manager(memory_manager), rasterizer{rasterizer} {}
: system{system}, rasterizer{rasterizer}, memory_manager{memory_manager} {}
KeplerMemory::~KeplerMemory() = default;

View File

@@ -10,12 +10,15 @@
#include "common/common_funcs.h"
#include "common/common_types.h"
#include "video_core/gpu.h"
#include "video_core/memory_manager.h"
namespace Core {
class System;
}
namespace Tegra {
class MemoryManager;
}
namespace VideoCore {
class RasterizerInterface;
}
@@ -82,8 +85,8 @@ public:
private:
Core::System& system;
MemoryManager& memory_manager;
VideoCore::RasterizerInterface& rasterizer;
MemoryManager& memory_manager;
void ProcessData(u32 data);
};

View File

@@ -7,11 +7,10 @@
#include "common/assert.h"
#include "core/core.h"
#include "core/core_timing.h"
#include "core/memory.h"
#include "video_core/debug_utils/debug_utils.h"
#include "video_core/engines/maxwell_3d.h"
#include "video_core/memory_manager.h"
#include "video_core/rasterizer_interface.h"
#include "video_core/renderer_base.h"
#include "video_core/textures/texture.h"
namespace Tegra::Engines {
@@ -21,8 +20,8 @@ constexpr u32 MacroRegistersStart = 0xE00;
Maxwell3D::Maxwell3D(Core::System& system, VideoCore::RasterizerInterface& rasterizer,
MemoryManager& memory_manager)
: memory_manager(memory_manager), system{system}, rasterizer{rasterizer},
macro_interpreter(*this) {
: system{system}, rasterizer{rasterizer}, memory_manager{memory_manager}, macro_interpreter{
*this} {
InitializeRegisterDefaults();
}
@@ -250,6 +249,10 @@ void Maxwell3D::CallMethod(const GPU::MethodCall& method_call) {
ProcessQueryGet();
break;
}
case MAXWELL3D_REG_INDEX(sync_info): {
ProcessSyncPoint();
break;
}
default:
break;
}
@@ -327,6 +330,14 @@ void Maxwell3D::ProcessQueryGet() {
}
}
void Maxwell3D::ProcessSyncPoint() {
const u32 sync_point = regs.sync_info.sync_point.Value();
const u32 increment = regs.sync_info.increment.Value();
const u32 cache_flush = regs.sync_info.unknown.Value();
LOG_DEBUG(HW_GPU, "Syncpoint set {}, increment: {}, unk: {}", sync_point, increment,
cache_flush);
}
void Maxwell3D::DrawArrays() {
LOG_DEBUG(HW_GPU, "called, topology={}, count={}", static_cast<u32>(regs.draw.topology.Value()),
regs.vertex_buffer.count);

View File

@@ -16,13 +16,16 @@
#include "common/math_util.h"
#include "video_core/gpu.h"
#include "video_core/macro_interpreter.h"
#include "video_core/memory_manager.h"
#include "video_core/textures/texture.h"
namespace Core {
class System;
}
namespace Tegra {
class MemoryManager;
}
namespace VideoCore {
class RasterizerInterface;
}
@@ -576,7 +579,17 @@ public:
u32 bind;
} macros;
INSERT_PADDING_WORDS(0x188);
INSERT_PADDING_WORDS(0x69);
struct {
union {
BitField<0, 16, u32> sync_point;
BitField<16, 1, u32> unknown;
BitField<20, 1, u32> increment;
};
} sync_info;
INSERT_PADDING_WORDS(0x11E);
u32 tfb_enabled;
@@ -1093,7 +1106,6 @@ public:
};
State state{};
MemoryManager& memory_manager;
struct DirtyFlags {
std::bitset<8> color_buffer{0xFF};
@@ -1141,6 +1153,8 @@ private:
VideoCore::RasterizerInterface& rasterizer;
MemoryManager& memory_manager;
/// Start offsets of each macro in macro_memory
std::unordered_map<u32, u32> macro_offsets;
@@ -1180,6 +1194,9 @@ private:
/// Handles a write to the QUERY_GET register.
void ProcessQueryGet();
/// Handles writes to syncing register.
void ProcessSyncPoint();
/// Handles a write to the CB_DATA[i] register.
void ProcessCBData(u32 value);
@@ -1195,6 +1212,7 @@ private:
"Field " #field_name " has invalid position")
ASSERT_REG_POSITION(macros, 0x45);
ASSERT_REG_POSITION(sync_info, 0xB2);
ASSERT_REG_POSITION(tfb_enabled, 0x1D1);
ASSERT_REG_POSITION(rt, 0x200);
ASSERT_REG_POSITION(viewport_transform, 0x280);

View File

@@ -5,9 +5,9 @@
#include "common/assert.h"
#include "common/logging/log.h"
#include "core/core.h"
#include "core/memory.h"
#include "video_core/engines/maxwell_3d.h"
#include "video_core/engines/maxwell_dma.h"
#include "video_core/memory_manager.h"
#include "video_core/rasterizer_interface.h"
#include "video_core/renderer_base.h"
#include "video_core/textures/decoders.h"
@@ -16,7 +16,7 @@ namespace Tegra::Engines {
MaxwellDMA::MaxwellDMA(Core::System& system, VideoCore::RasterizerInterface& rasterizer,
MemoryManager& memory_manager)
: memory_manager(memory_manager), system{system}, rasterizer{rasterizer} {}
: system{system}, rasterizer{rasterizer}, memory_manager{memory_manager} {}
void MaxwellDMA::CallMethod(const GPU::MethodCall& method_call) {
ASSERT_MSG(method_call.method < Regs::NUM_REGS,

View File

@@ -10,12 +10,15 @@
#include "common/common_funcs.h"
#include "common/common_types.h"
#include "video_core/gpu.h"
#include "video_core/memory_manager.h"
namespace Core {
class System;
}
namespace Tegra {
class MemoryManager;
}
namespace VideoCore {
class RasterizerInterface;
}
@@ -139,13 +142,13 @@ public:
};
} regs{};
MemoryManager& memory_manager;
private:
Core::System& system;
VideoCore::RasterizerInterface& rasterizer;
MemoryManager& memory_manager;
/// Performs the copy from the source buffer to the destination buffer as configured in the
/// registers.
void HandleCopy();

View File

@@ -1238,13 +1238,16 @@ union Instruction {
union {
BitField<20, 16, u64> imm20_16;
BitField<35, 1, u64> high_b_rr; // used on RR
BitField<36, 1, u64> product_shift_left;
BitField<37, 1, u64> merge_37;
BitField<48, 1, u64> sign_a;
BitField<49, 1, u64> sign_b;
BitField<50, 2, XmadMode> mode_cbf; // used by CR, RC
BitField<50, 3, XmadMode> mode;
BitField<52, 1, u64> high_b;
BitField<53, 1, u64> high_a;
BitField<55, 1, u64> product_shift_left_second; // used on CR
BitField<56, 1, u64> merge_56;
} xmad;
@@ -1662,7 +1665,7 @@ private:
INST("0011011-11110---", Id::BFI_IMM_R, Type::Bfi, "BFI_IMM_R"),
INST("0100110001000---", Id::LOP_C, Type::ArithmeticInteger, "LOP_C"),
INST("0101110001000---", Id::LOP_R, Type::ArithmeticInteger, "LOP_R"),
INST("0011100001000---", Id::LOP_IMM, Type::ArithmeticInteger, "LOP_IMM"),
INST("0011100-01000---", Id::LOP_IMM, Type::ArithmeticInteger, "LOP_IMM"),
INST("000001----------", Id::LOP32I, Type::ArithmeticIntegerImmediate, "LOP32I"),
INST("0000001---------", Id::LOP3_C, Type::ArithmeticInteger, "LOP3_C"),
INST("0101101111100---", Id::LOP3_R, Type::ArithmeticInteger, "LOP3_R"),

View File

@@ -31,7 +31,7 @@ u32 FramebufferConfig::BytesPerPixel(PixelFormat format) {
GPU::GPU(Core::System& system, VideoCore::RendererBase& renderer) : renderer{renderer} {
auto& rasterizer{renderer.Rasterizer()};
memory_manager = std::make_unique<Tegra::MemoryManager>();
memory_manager = std::make_unique<Tegra::MemoryManager>(rasterizer);
dma_pusher = std::make_unique<Tegra::DmaPusher>(*this);
maxwell_3d = std::make_unique<Engines::Maxwell3D>(system, rasterizer, *memory_manager);
fermi_2d = std::make_unique<Engines::Fermi2D>(rasterizer, *memory_manager);

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