Consistency change with how we mark constants in the rest of the
codebase.
Co-Authored-By: LC <712067+lioncash@users.noreply.github.com>
Co-authored-by: LC <712067+lioncash@users.noreply.github.com>
The list of points is returned by const reference, so we don't need to
make a copy of every element in the list.
Co-authored-by: Lioncash <mathew1800@gmail.com>
- In `SetCurrentThreadName`, when on Linux, truncate to 15 bytes, as (at
least on glibc) `pthread_set_name_np` will otherwise return `ERANGE` and
do nothing.
- Also, add logging in case `pthread_set_name_np` returns an error
anyway. This is Linux-specific, as the Apple and BSD versions of
`pthread_set_name_np return `void`.
- Change the name for CPU threads in multi-core mode from
"yuzu:CoreCPUThread_N" (19 bytes) to "yuzu:CPUCore_N" (14 bytes) so it
fits into the Linux limit. Some other thread names are also cut off,
but I didn't bother addressing them as you can guess them from the
truncated versions. For a CPU thread, truncation means you can't see
which core it is!
The general pattern is to mark mutexes as mutable when it comes to
matters of constness, given the mutex acts as a transient member of a
data structure.
Co-Authored-By: LC <lioncash@users.noreply.github.com>
These are intentionally discarded internally, since the rest of the
public API allows querying success. We want all non-internal uses of
these functions to be explicitly checked, so we can signify that we
intentionally want to discard the return values here.
The settings.h file doesn't actually need all of the definitions
on cam.h, only some of the enums. They can, therefore, be separated
into another file, which is included by settings.h instead.
The other changes are fixing files that included settings.h and
depended on indirect includes from includes of includes of cam.h
In all usages of LogSetting(), string literals are provided.
std::string_view is better suited here, as we won't churn a bunch of
string allocations every time the settings are logged out.
While we're at it, we can fold LogSetting() into LogSettings(), given
it's only ever used there.
Co-Authored-By: Mat M. <lioncash@users.noreply.github.com>
In cases where the size is not a known constant when inlining, AlignUp<std::size_t> currently generates two 64-bit div instructions.
This generates one div and a cmov which is significantly cheaper.
Some of the classes in this file already do this, so we can apply this
to the other ones to be consistent.
Allows these classes to play nicely and not churn copies when used with
standard containers or any other API that makes use of
std::move_if_noexcept.
* Change "Toggle Speed Limit" to toggle between 100% and a custom value
This will change the shortcut for "Toggle Speed Limit" to make it swap between 100% and the value of "Limit Speed Percent" in the config. Old functionality is still there, but renamed to "Unthrottle".
* Complete reimplementation of the function
* Fix something that didn't get saved correctly
* Fix missing indentation
* Rewrite to keep only a single QSpinBox
* Second rewrite
* set Unthrottled to 0 in the Qspinbox
* Hotkey for Unthrottle
* minor improvements to the design
* Apply suggestions from code review
Co-authored-by: Ben <bene_thomas@web.de>
* Default slider values
* clang-format fixes
* Prevent the speed slider from changing size
...when an element in its row has variable width.
* Change "Game Speed" to "Emulation Speed"
* Apply suggestions from code review
`game_speed` to` emulation_speed`
Co-authored-by: Valentin Vanelslande <vvanelslandedev@gmail.com>
* Fix for QSliders
* Revert "Prevent the speed slider from changing size"
This reverts commit ddaca20044.
* clang-format
...doesn't seem to stick to a choice
* Fix 2 for QSliders
Co-authored-by: B3n30 <benediktthomas@gmail.com>
Co-authored-by: Ben <bene_thomas@web.de>
Co-authored-by: Valentin Vanelslande <vvanelslandedev@gmail.com>
We can adjust the API to allow std::size_t indices, which simplifies
operating with standard container types. It also prevents truncation
warnings from occurring in these cases as well.
* archive: Make use of std::pair for OpenFileFromArchive
The tuple only makes use of two elements, so we can use a pair to
simplify the number of underlying template instantiations that need to
be done, while also simplifying the surrounding code.
* archive: Simplify MakeResult calls
MakeResult can deduce the contained result type based off the type of
the variable being passed to it, so explicitly specifying it is a little
verbose.
* Avoid deadlock when stopping video dumping
* Use static_cast, make quit atomic
* One more atomic load
* Use suggested lock instead of atomic
* Fix locking
While we're at it, we can also improve some of the allocations and
copying that would be going on in one case by preallocating and then
emplacing before modifying.
This might be caused by some packet/status delay within the enet protocol, or may be caused by our not properly handling disconnection. Anyway, this situation *can* happen, and we should not crash Citra for a non-critical error.
This change is not HW tested as I do not have 3 3DSes, but this should make sure that all the members of the network hold the same `node_info`, `nodes` and the bitmasks, etc.
Previously, when connecting, the host was using the incorrect node_id to update `node_info`.
This is an attempt to fix tywald's problem with MH, reported on Discord a while ago. I'm not sure if this would actually fix that though.
I'm not sure why we decided to have a boolean here, but apparently that wasn't the correct behaviour. According to HW tests, the Software Keyboard simply displays the default text when the button text provided is empty (**not necessarily all zero**). For example, if you set a text for one of the buttons and leave others empty, the button you set will have your text, while others will have their default texts. Removed the boolean and updated frontend code to make it correct.
* gl_rasterizer_cache: Mark file-scope functions as static where applicable
Prevents -Wmissing-declaration warnings from occurring and also makes
these functions internally linked.
* gl_rasterizer_cache: Remove unused local std::string variable
Despite being unused, compilers are unable to completely remove any code
gen related to the construction and destruction of this variable, since
the destructor of std::string is non-trivial.
Thus, we can remove it to reduce a minor amount of unnecessary code
generation
* gl_rasterizer_cache: Mark hash implementation as noexcept
This shouldn't throw.
* gl_rasterizer_cache: Remove unused variable in ClearAll()
* gl_rasterizer_cache: Make use of const on references explicit
While declared as auto&, these actually behave as const auto& variables,
due to the constness of the container being iterated. We can make this
explicit for readability sake.
* gl_rasterizer_cache: Resolve truncation warnings
The size is forwarded to a std::memset call, which takes a std::size_t
as its size parameter, so we can just make this change to silence the
warnings.
* gl_rasterizer_cache: Resolve variable shadowing warnings
Prevents a -Wshadow warning from occurring.
* GUI: Deadzone controls for sdl engine at configuration input
Co-Authored-By: CJ Bok <cjbok@users.noreply.github.com>
* configure_input: Use slider to edit modifier scale
Co-Authored-By: Kewlan <kewlan@users.noreply.github.com>
* Address minor review comment
Co-Authored-By: Kewlan <kewlan@users.noreply.github.com>
Co-authored-by: CJ Bok <cjbok@users.noreply.github.com>
Co-authored-by: Kewlan <kewlan@users.noreply.github.com>
It's undefined behavior to pass a null pointer to std::fread and
std::fwrite, even if the length passed in is zero, so we must perform
the precondition checking ourselves.
A common case where this can occur is when passing in the data of an
empty std::vector and size, as an empty vector will typically have a
null internal buffer.
While we're at it, we can move the implementation out of line and add
debug checks against passing in nullptr to std::fread and std::fwrite.
Prevents the internal buffer in the std::optional from being zeroed out
unnecessarily and instead sets the validity byte only in some
implementations.
While we're at it, we can make use of std::move to eliminate unnecessary
heap reallocations from occurring.
Allows us to avoid even more string churn by allowing the AddLine
function to make use of fmt formatting so the string is formatted all at
once instead of concatenating multiple strings.
This is similar to how yuzu's decompiler works, which I've made function
the same way in the past.
Quite a few service functions are stubbed but still pop all their
arguments, which can lead to unused variable warnings.
We can mark the unused arguments with [[maybe_unused]] to silence these
warnings until a full implementation of these functions are made.
Allows implementations to allocate the object and the shared_ptr control
block in one allocation instead of needing to do two separate
allocations.
Also looks much nicer to the reader.
* swkbd: Fix a bug where clicking Cancel hangs the game
The text is validated in `Finalize`. If the validation fails, an error is returned and the applet is not actually finalized. This can result in hangs.
This is usually not a problem as the frontend is expected to validate the text passed to `Finalize`. However, when the user clicked on `Cancel`, the text is ignored and the frontend won't do any validation. Therefore, we should skip the validation here as well.
Also fixed a potential data race. All these functions should now be called on the same thread
* Address review comments
Renamed the fields
Remove close button
This class is memcpy-ed and memcpy has the requirement that data passed
to it must be trivially copyable, otherwise the behavior is undefined.
This is trivial to resolve as BitField was made trivially copyable a
while ago, so this explicit copy assignment operator isn't necessary.
This can be removed as it's not used. Even if it were however, it would
be an incorrect forward declaration, as ServiceManager exists within the
Service::SM namespace, not the top-level SM namespace.
Same behavior, no heap allocation.
strings returned from glGetString() are guaranteed to be static strings,
so this is safe to do. They're also guaranteed to be null-terminated.
Some implementations can use the std::nullopt_t constructor of
std::optional to avoid needing to completely zero out the internal
buffer of the optional and instead only set the validity byte within it.
e.g. Consider the following function:
std::optional<std::vector<ShaderDiskCacheRaw>> fn() {
return {};
}
With libc++ this will result in the following code generation on x86-64:
Fn():
mov rax, rdi
vxorps xmm0, xmm0, xmm0
vmovups ymmword ptr [rdi], ymm0
vzeroupper
ret
With libstdc++, we also get the similar equivalent:
Fn():
vpxor xmm0, xmm0, xmm0
mov rax, rdi
vmovdqu XMMWORD PTR [rdi], xmm0
vmovdqu XMMWORD PTR [rdi+16], xmm0
ret
If we change this function to return std::nullopt instead, then this
simplifies both the code gen from libc++ and libstdc++ down to:
Fn():
mov BYTE PTR [rdi+24], 0
mov rax, rdi
ret
Given how little of a change is necessary to result in better code
generation, this is essentially a "free" very minor optimization.
Previously, we were returning a value that was way too big, causing an integer overflow in Fractured Souls.
According to wwylele, the biggest oberserved save size for 3DS is 1MB, so this new value should leave plenty of room, even if games use a bigger size.
Many of these functions are capable of being used within const contexts,
so we can apply the const qualifier in some cases and add const based
overloads for others, which makes the interface a little bit more
flexible and const-correct.
* core/memory: Amend unusual return value of operator=
operator= usually returns a reference to this. Given there's no comment
explaining why void was used, this can be assumed to be an oversight.
* core/memory: Make use of std::move in Entry::operator=
Same behavior, minus the need for an atomic reference count increment
and decrement (since MemoryRef contains a std::shared_ptr).
* ArmInterface: return ref instead of copy for GetTimer
* ArmInterface: add const ref GetTimer
* ArmInterface: return raw pointer instead of shared_ptr in GetTimer
* remove more unnecessary shared_ptr usage
* Fix save states
* fix unit tests
* video_core: reduce string allocations in shader decompiler
* use append for indentation instead of resize
Co-authored-by: Mat M. <mathew1800@gmail.com>
* am/am: Avoid redundant copy in GetProgramInfoFromCia()
We can just use a reference to the title metadata. Avoids copying
several data entries and std::vector instances that don't need to be
copied.
* hle/service: Avoid redundant copying of std::string
GetUserPath() returns the path as a reference, so we can make use of
said reference to avoid making copies.
By using a reference here, we avoid copying every single element in the
map, each of which contains a std::share_ptr and std::deque containing
std::vectors.
Same behavior, but doesn't result in an allocating copy of the passed in
string. Particularly given the string is only compared against other
existing strings.
Several standard constructors generally check if objects can be moved in
a non-throwing manner (usually via std::move_if_noexcept) to preserve
its exception guarantees. This means that if these were used with
certain containers any reallocations internally would cause resource
churn, as copies would be necessary instead of moves.
This way, if they're every used in that manner, the right behavior is
always performed.
Avoids copying the std::function when we don't need to. Particularly
given the std::function isn't actually stored anywhere, so there's no
need to move it.
Allows interfaces to move the vector into the calls, avoiding any
reallocations.
Many existing call sites already std::move into the parameter, expecting
a move to occur. Only a few remain where this wasn't already
being done, which we can convert over.
This one is similar to the ReceiveCaptureBufferInfo function except it doesn't clear the capture buffer, according to 3dbrew.
This function is used by the Home Menu
The Home Menu uses this to determine whether it is allowed to launch an app (call StartApplication)
This is a no-op for us, we allow any and all titles to be launched. The official APT module holds a list of some forbidden titles like some versions of IronFall and Flipnote Studio 3D.
On Windows, network shares use paths like \\server\share\file which were
being broken by FileUtil::SanitizePath() removing double slashes.
Changed the code in SanitizePath to permit a double-backslash if it
occurs at the start of a filepath (on Windows only).
They are called by the Home Menu during initialization.
These functions will not see much use until we actually implement application jumping and system rebooting. For now we just need them to prevent some unmapped reads in the Home Menu due to the static buffers not being properly set up.
Also rewritten how GetArchiveResource works so that they all use the same interface.
We should decide what to do with these at some point.
Related to #3131 and #3110
* Kernel/Process: Notify the CPUs that a new pagetable has been set every time the process they're executing changes.
Previously the page table would only be changed when the current CPU's page table was changed, this lead to stale JIT states and the PC going to 0 when context-switching a different core inside the ThreadManager::SwitchContext function because the JIT for a new pagetable is only constructed upon receiving the change notification.
* Kernel/Process: Use the relevant CPU's last process to determine when to switch its current process.
Previously it was checking the kernel's current_process variable, which gets overwritten every time a CPU runs its slice. The rescheduling happens after all CPUs have run their slice so the code was effectively only checking the last CPU's process.
* Add and implement option to hide mouse on iniactivity
+ clang format
* Set mouse hide timeout as a constant
* Address review comments, decrease mouse inactivity timeout to 2500ms
* Hide mouse: fix menubar bugs
squashable
* Hide mouse: ensure status bar has the default pointer
This fixes#5067 by reverting a speculative change made in a previous PR.
From this one can conclude that, for disabled textures, black (0,0,0,1) is the correct colour and clear (0,0,0,0) is not.
* video_core/renderer_opengl/gl_rasterizer_cache: Create Format Reinterpretation Framework
Adds RGBA4 -> RGB5A1 reinterpretation commonly used by virtual console
If no matching surface can be found, ValidateSurface checks for a surface in the cache which is reinterpretable to the requested format.
If that fails, the cache is checked for any surface with a matching bit-width. If one is found, the region is flushed.
If not, the region is checked against dirty_regions to see if it was created entirely on the GPU.
If not, then the surface is flushed.
Co-Authored-By: James Rowe <jroweboy@users.noreply.github.com>
Co-Authored-By: Ben <b3n30@users.noreply.github.com>
temporary change to avoid merge conflicts with video dumping
* re-add D24S8->RGBA8 res_scale hack
* adress review comments
* fix dirty region check
* check for surfaces with invalid pixel format, and break logic into separate functions
1. Ensure that register information available to gdbstub is most up-to-date.
2. There's no reason to check for current_thread == thread when emitting a trap.
Doing this results in random hangs whenever a step happens upon a thread switch.
* video_core/renderer_opengl: Move SurfaceParams into its own file
Some of its enums are needed outside of the rasterizer cache
and trying to use it caused circular dependencies.
* video_core/renderer_opengl: Overhaul the texture filter framework
This should make it less intrusive.
Now texture filtering doesn't have any mutable global state.
The texture filters now always upscale to the internal rendering resolution.
This simplifies the logic in UploadGLTexture and it simply takes the role of BlitTextures at the end of the function.
This also prevent extra blitting required when uploading to a framebuffer surface with a mismatched size.
* video_core/renderer_opengl: Use generated mipmaps for filtered textures
The filtered guest mipmaps often looked terrible.
* core/settings: Remove texture filter factor
* sdl/config: Remove texture filter factor
* qt/config: Remove texture filter factor
* HLE Audio: Increase frame position by input buffer sample rate
Currently the frame position moves ahead by the number of samples
output, but thats a fixed number based on the 3ds native sample rate.
Instead, based on a homebrew by cyuubi and looking at the lle audio,
this sample position should be moved forward by the number of samples
from the input buffer that was read, based on the buffer's sample rate.
* vm_manager: Handle multiple areas in ChangeMemoryState
It is possible that a few areas have the same permisson and state, but with different backing pointers. Currently, this function assumes that only one continous area is found, but this is not always the case.
* service/ldr_ro: Handle multiple areas in VerifyBufferState
It is possible that the buffer passed from the game is made up of multiple areas with the same permisson and state but different backing pointers. Change the check to allow that.
* IOFile: Make the move constructor and move assignment operator noexcept
Certain parts of the standard library try to determine whether or not a
transfer operation should either be a copy or a move. The prevalent notion
of move constructors/assignment operators is that they should not throw,
they simply move an already existing resource somewhere else.
This is typically done with 'std::move_if_noexcept'. Like the name says,
if a type's move constructor is noexcept, then the functions retrieves an
r-value reference (for move semantics), or an l-value (for copy semantics)
if it is not noexcept.
As IOFile deletes the copy constructor and copy assignment operators,
using IOFile with certain parts of the standard library can fail in
unexcepted ways (especially when used with various container
implementations). This prevents that.
* fix various instances of -1 being assigned to unsigned types
* do not assign in conditional statements
* File/IOFile: Check _tfopen_s properly
* common/file_util.cpp: address review comments
Co-authored-by: Lioncash <mathew1800@gmail.com>
Co-authored-by: Shawn Hoffman <godisgovernment@gmail.com>
Co-authored-by: Sepalani <sepalani@hotmail.fr>
When dumping was stopped, the game will be paused and then resumed. However when the game was already paused this will result in the game being unexpectedly resumed, which isn't what we want.
The most important one being adding a mutex to protect the format_context. Apparently it wasn't thread safe (as one'd expect) but I didn't think about that.
Should fix some of the strange issues happening with MP4 muxers, etc.
src/video_core/renderer_opengl/texture_filters/bicubic/bicubic.cpp:51:86: error: cannot initialize a parameter of type 'GLuint' (aka 'unsigned int') with an rvalue of type 'nullptr_t'
glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, NULL, 0);
^~~~
src/video_core/renderer_opengl/texture_filters/xbrz/xbrz_freescale.cpp:95:86: error: cannot initialize a parameter of type 'GLuint' (aka 'unsigned int') with an rvalue of type 'nullptr_t'
glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, NULL, 0);
^~~~
/usr/include/sys/_null.h:37:14: note: expanded from macro 'NULL'
#define NULL nullptr
^~~~~~~
The main problem is the loss of compatibility with some controllers, but there are also
unwanted changes to the behaviour of PS4 controllers (hardcoded lightbar color).
The file's size is stored in FileSessionSlot and retrieved when the game calls GetSize. However, it is not updated when the file is written to, which can possibly change the file size. Therefore, this can cause GetSize to return incorrect results.
According to HW tests, this vsync event is signaled for activated cameras at about the same frequency as the frame rate. The last 5 vsync timings are recorded (in microseconds) and can be retrieved with the service function.
Also, corrected the default frame_rate to 15, according to HW test.
This should fix the missing camera images in certain games.
The default is discrete_interval which has dynamic open-ness.
We only use right_open intervals anyway. In theory this could allow some compile-time optimizations.
You can now directly place ExeFS overrides/patches inside the mod folder (instead of the exefs subfolder). This allows us to have drop-in compatibility with Luma3DS mods.
This is the main dialog of video dumping. This dialog allows the user to set output format, output path, video/audio encoder and video/audio bitrate.
When a format is selected, the list of video and audio encoders are updated. Only encoders of codecs that can be contained in the format is shown.
This dialog allows changing the value and unsetting one option. There are three possible variants of this dialog:
1. The LineEdit layout. This is used for normal options like string and duration, and just features a textbox for the user to type in whatever they want to set.
2. The ComboBox layout. This is used when there are named constants for an option, or when the option accepts an enum value like sample_format or pixel_format. A description will be displayed for the currently selected named constant. The user can also select 'custom' and type in their own value.
3. The CheckBox-es layout. This is used for flags options. A checkbox will be displayed for each named constant and the user can tick the flags they want to set.
These two functions allow the frontend to get a list of encoders/formats and their specific options.
Retrieving the options is harder than it sounds due to FFmpeg's strange AVClass and AVOption system. For example, for integer and flags options, 'named constants' can be set. They are of type `AV_OPT_TYPE_CONST` and are categoried according to the `unit` field. An option can recognize all constants of the same `unit`.
Previously, we just used the native sample rate for encoding. However, some encoders like libmp3lame doesn't support it. Therefore, we now use a supported sample rate (preferring the native one if possible).
FFmpeg requires audio data to be sent in a sequence of frames, each containing the same specific number of samples. Previously, we buffered input samples in FFmpegBackend. However, as the source and destination sample rates can now be different, we should buffer resampled data instead. swresample have an internal input buffer, so we now just forward all data to it and 'gradually' receive resampled data, at most one frame_size at a time. When there is not enough resampled data to form a frame, we will record the current offset and request for less data on the next call.
Additionally, this commit also fixes a flaw. When an encoder supports variable frame sizes, its frame size is reported to be 0, which breaks our buffering system. Now we treat variable frame size encoders as having a frame size of 160 (the size of a HLE audio frame).
We previously assumed that the first preferred sample format is planar, but that may not be true for all codecs. Instead we should find a supported sample format that is planar.
While YUV420P is widely used, not all encoders accept it (e.g. Intel QSV only accepts NV12). We should use the codec's preferred pixel format instead as we need to rescale the frame anyway.
This uses the mailbox model to move pixel downloading to its own thread, eliminating Nvidia's warnings and (possibly) making use of GPU copy engine.
To achieve this, we created a new mailbox type that is different from the presentation mailbox in that it never discards a rendered frame.
Also, I tweaked the projection matrix thing so that it can just draw the frame upside down instead of having the CPU flip it.
* audio_core: dsp_hle: implements fdk_aac decoder
* audio_core: dsp_hle: clean up and add comments
* audio_core: dsp_hle: move fdk include to cpp file
* audio_core: dsp_hle: detects broken fdk_aac...
... and refuses to initialize if that's the case
* audio_core: dsp_hle: fdk_aac: address comments...
... and rebase commits
* fdk_decoder: move fdk header to cpp file
* videocore/renderer_opengl/gl_rasterizer_cache: Move bits per pixel table out of function
GCC and MSVC copy the table at runtime with the old implementation, which is wasteful and prevents inlining. Unfortunately, static constexpr variables are not legal in constexpr functions, so the table has to be external.
Also replaced non-standard assert with DEBUG_ASSERT_MSG.
* fix case of table name in assert
* set table to private
This slider affects the number of cycles that the guest cpu emulation
reports that have passed since the last time slice. This option scales
the result returned by a percentage that the user selects. In some games
underclocking the CPU can give a major speedup. Exposing this as an
option will give users something to toy with for performance, while also
potentially enhancing games that experience lag on the real console
* Core::Timing: Add multiple timer, one for each core
* revert clang-format; work on tests for CoreTiming
* Kernel:: Add support for multiple cores, asserts in HandleSyncRequest because Thread->status == WaitIPC
* Add some TRACE_LOGs
* fix tests
* make some adjustments to qt-debugger, cheats and gdbstub(probably still broken)
* Make ARM_Interface::id private, rework ARM_Interface ctor
* ReRename TimingManager to Timing for smaler diff
* addressed review comments
* HTTP_C::Implement Context::MakeRequest
* httplib: Add add_client_cert_ASN1 and set_verify
* HTTP_C: Fix request methode strings case in MakeRequest
* HTTP_C: clang-format and cleanups
* HTTP_C: Add comment about async in BeginRequest and BeginRequestAsync
* Update httplib to contain all the changes we need; adapt http_c and web_services to the changes in httplib; addressed minor review comments
* Add android-ifaddrs
10 slots are offered along with 'Save to Oldest Slot' and 'Load from Newest Slot'.
The savestate format is similar to the movie file format. It is called CST (Citra SavesTate), and is basically a 0x100 byte header (consisting of magic, revision, creation time and title ID) followed by Zstd compressed raw savestate data.
The savestate files are saved to the `states` folder in Citra's user folder. The files are named like `<Title ID>.<Slot ID>.cst`.
* yuzu/CMakeLists: Disable implicit QString conversions
Now that all of our code is compilable with implicit QString
conversions, we can enforce it at compile-time by disabling them.
Co-Authored-By: Mat M. <lioncash@users.noreply.github.com>
* citra_qt: Remove lots of implicit QString conversions
Co-authored-by: Mat M. <mathew1800@gmail.com>
std::function is allowed to heap allocate if the size of the captures
associated with each lambda exceed a certain threshold. This prevents
potentially unnecessary reallocations from occurring.
This holds the archives which include the SelfNCCH archive which holds the RomFS files. If we don't reset it the LayeredFS class can't get destructed and mods files won't be released.