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.
The original path (file_name.exefsdir) is still supported, but alternatively users can choose to put exefs patches in the same place as LayeredFS files (`load/mods/<Title ID>/exefs`).
Only enabled for NCCHs that do not have an override romfs.
LayeredFS files should be put in the `load` directory in User Directory. The directory structure is similar to yuzu's but currently does not allow named mods yet. Replacement files should be put in `load/mods/<Title ID>/romfs` while patches/stubs should be put in `load/mods/<Title ID>/romfs_ext`.
This implementation is different from Luma3DS's which directly hooks the SDK functions. Instead, we read the RomFS's metadata and figure out the directory and file structure. Then, relocations (i.e. replacements/deletions/patches) are applied. Afterwards, we rebuild the metadata, and assign 'fake' data offsets to the files. When we want to read file data from this rebuilt RomFS, we use binary search to find the last data offset smaller or equal to the given offset and read from that file (either from the original RomFS, or from replacement files, or from buffered data with patches applied) and any later files when length is not enough.
The code that rebuilds the metadata is pretty complex and uses quite a few variables to keep track of necessary information like metadata offsets. According to my tests, it is able to build RomFS-es identical to the original (but without trailing garbage data) when no relocations are applied.
The DIGIT filter was incorrectly implemented as preventing all digits. It actually limits the maximum digit count to max_digits, according to ctrulib and hardware testing.
- We have some important audio settings, makes them more discoverable.
Co-Authored-By: bunnei <bunneidev@gmail.com>
Co-authored-by: bunnei <bunneidev@gmail.com>
Until we get a on screen display or async shader loading, we should at
least have some measure of progress in the meantime. This is 90% a port
from the loading screen I made for yuzu, but with a slightly different
changed detection for when to display the ETA. Now we keep track of a
rolling estimate for shader load ETA and only display a ETA if its going
to take longer than 10 seconds.
This is based on what was done using additional layouts, but modified
to have a variable to control rotation and making it so Single Screen
Layout behaves like Upright Single would, and Default Layout behaves
like Upright Double would, when the new variable is used.
Large Layout and Side Layout currently ignore the new variable.
New variable still currently doesn't have a hotkey.
The BPS format allows distributing patches that are smaller and that do
not contain copyrighted content if data is relocated
(unlike non-trivial IPS patches).
This is essential for games such as MM3D that have three barely
different code revisions. Supporting all three versions would
demand an unreasonable amount of work; with BPS patches only one
version has to be supported.
This changes ApplyCodePatch to return a ResultStatus, which makes it
possible to determine whether patch applying has failed. Previously,
only a boolean was returned, and false was returned when no patch
was found OR when a patch was found but applying it failed.
This also changes AppLoader_NCCH to return an error if patching fails
because the executable is likely to be left in an inconsistent state
and we should not proceed booting in that case.
This significantly reduces unnecessary disk writes and space usage
when building Citra.
libcore.a is now only ~1MB rather than several hundred megabytes.
Previously we would first attempt to use any buffer that was free,
meaning whichever buffer has already been displayed. This has poor
interactions when the operating system throttles the update rate of the
window, so if there isn't any free buffers available, just reuse the
oldest frame instead.
Simple cut/paste issue where initialized is only set to true when the
emulation attempts to init the Binary Pipe, but we used it to test if
the FFMPEG decoder was valid and disabled it if it wasn't. Just return
the value of have_ffmpeg_dl instead so when dynamic loading is added
it'll still work.
HACK
In Luigi's Mansion Dark Moon in HLE audio, the game mysteriously passes
in an extremely large value for length, which without any checks, causes
HLE audio to allocate an extremely large buffer.
This value seemingly is caused by some other HLE audio feature is missing,
and Luigi's Mansion subtracts two values to get a length, without
checking for overflow first. This appears to be caused by an incorrect
HLE audio emulation, as its fixed entirely by only changing to LLE. As
such, further investigation is required, but in the meantime, completely
eating up our users RAM is unacceptable.
The text shared memory wasn't supposed to be cleared according to my comparison with the LLE swkbd. This can cause issues in certain games such as Harvest Moon.
A null terminator is added to the text copied to mark the end of the string.
Fixes an issue where the touch point is incorrect in OpenGLWindow when the render
target is initialized for the first time with single window mode disabled.
While QOpenGLWidget sounds like a good idea, it has issues which are
harder to debug due to how Qt manages the context behind the scenes. We
could probably work around any of these issues over time, but its
probably easier to do it ourselves with a QWindow directly.
Plus using QWindow + createWindowContainer is the easiest to use
configuration for Qt + Vulkan so this is probably much better in the
long run.
Over time our config values have grown quite numerous in size.
Unfortunately it also makes the single functions we have for loading and
saving values more error prone.
For example, we were loading the core settings twice when they only
should have been loaded once. In another section, a variable was
shadowing another variable used to load settings from a completely
different section.
Finally, in one other case, there was an extraneous endGroup() call used
that didn't need to be done. This was essentially dead code and also a
bug waiting to happen.
This separates the section loading code into its own separate functions.
This keeps variables only visible to the code that actually needs it,
and makes it much easier to visually see the end of each individual
configuration group. It also makes it much easier to visually catch bugs
during code review.
While we're at it, this also uses QStringLiteral instead of raw string
literals, which both avoids constructing a lot of QString instances, but
also makes it much easier to disable implicit ASCII to QString and
vice-versa in the future via setting QT_NO_CAST_FROM_ASCII and
QT_NO_CAST_TO_ASCII as compilation flags.
We relies on UNREACHABLE's noreturn attribute to eliminate parent's "no return value" warning. However, this was wrapped in a `if(!false)` block, which compilers may not unfold to recognize the noreturn nature.
By default, DisplayRole is used as the SortRole.
This behaviour is what's expected by the user.
Made it so that an access to SortRole is equivalent to one to DisplayRole.
Also fixes a bug with directory sorting.
Also fix a small issue with incorrect shutdown ordering in SDL.
Previously the system would still be running so the telemetry task
didn't launch and detached_tasks would assert(count == 0)