The only call of `IsScannerReady` was removed by
81be0001a9, and most of the `IsReady`
functions were only called by `IsScannerReady`.
The one exception was in `WiimoteScannerLinux`, which is now a private
function instead of inheriting from the one in `WiimoteScannerBackend`.
Fix incorrect scaling of the gap drawn inside enabled breakpoints in
BreakpointWidget when breakpoints are globally disabled and the font
size is changed from the default.
As the font size increased the gap would become larger and its center
would "migrate" downward and rightward until the gap stopped being
visible at all.
Additionally, at small font sizes integer truncation issues could result
in the gap being offset towards the top left.
Use `sizeHint` instead of `setMinimumSize` to increase the default size
of `StickWidget` and `IRWidget`.
0531286906 doubled the initial sizes of
`StickWidget` and `IRWidget`, but using `setMinimumSize` to do so
prevented users from shrinking the widgets manually.
Resolves bugs.dolphin-emu.org/issues/14019.
Rename `AUTO_UPDATE_BETA_INDEX` to `AUTO_UPDATE_RELEASE_INDEX` and
`AUTO_UPDATE_BETA_STRING` to `AUTO_UPDATE_RELEASE_STRING`.
Add a comment explaining that `AUTO_UPDATE_RELEASE_STRING = "beta"` for
backward compatibility reasons.
Set the default value of `Config::MAIN_WASAPI_DEVICE` to `default`
instead of `Default`. This fixes an issue where `AudioPane`'s `Output
Device` combo would be blank if `WASAPI` was selected and the user had
never changed the value of `Output Device`.
We don't have to worry about backward compatibility with users who have
`Default` in their config because config values aren't written unless
they've been changed at some point from the default, and the combo has
always saved `default` instead of `Default`.
Audio still worked during emulation in this situation because the
fallback for an unrecognized device name is the default device.
To help prevent similar situations in the future references to
`MAIN_WASAPI_DEVICE`'s default value now call `GetDefaultValue` instead
of hardcoding the expected default, or use the new helper function
`Config::IsDefaultValue`.
Don't copy null terminators from the log's `header.gameid` into
`FifoDataFile`'s `m_game_id`.
Doing so would cause an infinite loop in `Core::GenerateScreenshotName`
as the various concatenations and `fmt::format` calls would then
effectively drop all the timestamps and disambiguating arbitrary numbers
since they followed the null terminator in the gameid, and so the
`File::Exists` calls would always return true.
Fixes https://bugs.dolphin-emu.org/issues/14002.
Check the return value of calls to `GetBuffer` and stop the `WASAPI
handler` sound thread if they fail.
This prevents a crash due to a null pointer dereference if `GetBuffer`
is unable to retrieve a buffer, which could be triggered during
emulation by disabling the selected WASAPI output device in the Windows
Sound settings.
The status bar shows the number of games in your collection. If any
games are hidden by the platform, region, or search filters it will also
show how many games are visible and how many are filtered.
The visibility of the status bar can be toggled from the menu by
selecting `View`->`Show Game Count`.
Implements https://bugs.dolphin-emu.org/issues/9517.
Use the normal state changed `HookableEvent` instead of having
`Core::NotifyStateChanged` call `g_perf_metrics.OnEmulationStateChanged`
directly.
The direct call was added in bad78cfed4 to
avoid a crash. At the time state changed callbacks were stored in a
vector, and the crash was caused by `g_perf_metric`'s destructor trying
to remove the callback from the already-destroyed vector.
Later a97627e736 switched state changed
callbacks to use `HookableEvent`, which is specifically designed to
handle the case where a hook outlives its associated event.
Since the workaround is no longer necessary replace it with a standard
`EventHook`.
Don't set cached array bases to invalid pointers. If a game tries to set
an invalid base just keep the old one, which might cause game problems
but won't crash the emulator.
Call `OnStateChanged` when creating CheatsManager to update the AR and
Gecko code tabs with codes for the currently running game (if any).
Previously, creating CheatsManager while a game was running wouldn't
show any codes until the next time the core state changed (excluding
Starting or Stopping which had no effect).
Fixes https://bugs.dolphin-emu.org/issues/13977.
Add a minimum value for the automatic size of the performance metrics
graph. The graph can still be manually resized smaller than this limit.
This prevents the graph from automatically resizing itself to be too
small to contain the full graph and legend, which happened when using
native resolution with `Auto-Adjust Window Size` enabled.
Fix a bug causing the performance graph to not resize when the render
window changed size:
* When changing the render window size during emulation the performance
graph wouldn't update its size until the next emulation session.
* When changing the render window size with no emulation active (by
changing the Internal Resolution with Auto-Adjust Window Size enabled)
the performance graph wouldn't update its size until the second
emulation session after the change.
Before explaining why the bug happened, here are some details about Dear
ImGui (henceforth ImGui) for context:
* In order to allow programs to specify initial ImGui window sizes while
also allowing the user to resize them, `SetNextWindowSize` takes a
flag from the `ImGuiCond_` enum specifying under what circumstances
that function should actually have any effect.
* ImGuiCond_FirstUseEver causes ImGui to only apply the command when the
window doesn't have any saved size information for that session or in
the ini file specified by `ImGui::GetIO().IniFilename`. Since we set
that filename to `nullptr`, in practice the resize command is applied
on the first frame of each ImGui/emulation session.
* Qt saves the most recent size of the render window across emulation
(and even Dolphin) sessions, which is then used to set the initial
value of `ImGui::GetIO().DisplaySize` in the next emulation session.
* It takes multiple frames for the size of the render window to update
when changed by setting the internal resolution. This means that
`ImGui::GetIO().DisplaySize` will have a stale value in the
intervening frames, and specifically for the first few frames of
emulation if the resolution was changed beforehand.
When changing the resolution during emulation the call to
`SetNextWindowSize` had no effect because of the
`ImGuiCond_FirstUseEver` flag. `DisplaySize` would be updated several
frames later, and then the next emulation session would update the graph
size on its first frame.
When changing the resolution outside emulation and then starting a game,
the call to SetNextWindowSize on the first frame took effect but used
the stale value of `DisplaySize`. `DisplaySize` would be updated a few
frames later, but the graph wouldn't be resized until the first frame of
the second emulation session.
This commit fixes the issue by using the `ImGuiCond_Always` flag in the
performance graph's call to `SetNextWindowSize` when the render window
size changes.
Remove unused vector `controller_names` from `LoadConfig` and
`SaveConfig`. The vector has names added to it but they're never used.
Prior to d03f9032c1 these vectors were
passed to `DynamicInputTextureManager::GenerateTextures`, but that
commit removed those calls.
If the call to `Open` a perf map fails don't set `s_is_enabled` (though
it could already be true if you're also using VTUNE) and don't call
`std::setvbuf` with a null stream.
Also fix a typo in a comment (`if` -> `in`)
The check only happened if `USE_VTUNE` wasn't defined, and in that case
it was immediately followed by the same check again.
The check used to avoid an unnecessary call to `StringFromFormatV` in
certain circumstances, but that call was removed in
be81fe86e1.
CMake support for c++23 was added in 3.20.
Remove statements explicitly setting the following policies to NEW.
These policies were introduced in or before 3.20, and now that 3.20 is
the minimum version they will automatically have the NEW behavior.
Policy: Introduced in
CMP0079: 3.13
CMP0084: 3.14
CMP0091: 3.15
CMP0092: 3.15
CMP0099: 3.17
CMP0117: 3.20
Disable scanning c++ source files for module imports (introduced as
CMP0155 in 3.28) since we don't use modules and that policy triggers
build errors with Clang if the clang-scan-deps tool isn't installed.
Move the constructor and destructor after the definition of the class
`Internal`.
This fixes an error generated by Clang from the destructor of
`std::unique_ptr<Internal>` when setting the standard version to c++23:
`invalid application of 'sizeof' to an incomplete type 'Metal::ObjectCache::Internal'`.
Fix an error generated by Clang from the destructor of
`std::unique_ptr<FileInfo> m_file_info` when setting the standard
version to c++23:
`invalid application of 'sizeof' to an incomplete type 'DiscIO::FileInfo'`
Aside from being unnecessary, on Windows the flag prevents two instances
of Dolphin (one instance from before 2509-371 when the flag was
introduced and the other after) from running the same ROM
simultaneously.
Attempting to do so generated the false error `"[Rom]" is an invalid
GCM/ISO file, or is not a GC/Wii ISO.` followed by `Failed to init core`
and emulation shutdown on the second instance to start the game. Fixing
the incorrect error message is a task I'm deferring to another PR.
The problem didn't happen when both instances were 2509-371 or later,
but I ran into it while bisecting an issue and it'd be nice to avoid
that problem in the future.
Call `UseNoImm` instead of `Use` on parameter `a` of `MultiplyImmediate`
since `Ra` gets passed to `IMUL` which asserts that parameter is not an
immediate.
Push and wait on WorkQueueThread items using PushBlocking. Previously we
created a Common::Event sync_event on the caller's stack, called Wait on
it, then had the WorkQueueThread call Set on the sync_event once the
thread was done.
In addition to being simpler the new way avoids a use-after-free that
could happen in convoluted and unlikely yet possible thread scheduling
sequences.
One such case can be triggered as follows:
* Set your audio backend to Cubeb
* In CubebStream::SetVolume set a breakpoint at the call to Wait and at
the call to cubeb_stream_set_volume.
* Start a game.
* Continue until the Cubeb Worker thread hits the
cubeb_stream_set_volume breakpoint and Emuthread hits the Wait
breakpoint, freezing each thread when it hits its breakpoint.
* Unfreeze Cubeb Worker.
* In Event::Set set a breakpoint at the end of the scope containing the
lock_guard such that the guard has been constructed but not destructed
when the breakpoint is hit.
* Continue until that breakpoint is hit by Cubeb Worker. If other
threads hit it first keep going.
* Freeze Cubeb Worker.
* For convenience remove the breakpoint in Event::Set so other threads
don't trigger it.
* In CubebStream::SetRunning set a breakpoint at the call to Wait.
* Unfreeze Emuthread and continue until the breakpoint is hit.
* In Cubeb Worker go to Event::Set and examine the values of m_mutex's
member variables. In Visual Studio Debug these are locking_thread_id
== 0xcccccc01 and ownership_levels == 0xcccccccc. This is the result
of Visual Studio overwriting the memory used on the stack by
sync_event in CubebStream::SetVolume with cc bytes to represent
uninitialized memory on the stack (since that function already
returned), and then allocating enough memory on the stack when calling
AudioCommon::SetSoundStreamRunning and then CubebStream::SetRunning
that it overwrote one byte of the memory formerly occupied by
locking_thread_id.
* If you unfreeze Cubeb Worker at this point it will trigger the lock
guard's destructor which will then try to unlock m_mutex. Since
m_mutex is no longer in scope this is a use-after-free, and in VS
debug triggers a debug assert due to locking_thread_id not matching
the current thread id.
Remove "env, " from "return env, GetControlPointer..." since the left
side of a comma operator has no effect.
This was presumably a copy/paste error from the function above it.
PauseAndLock is now only called with do_lock=true, and unpause_on_unlock
only ever was used when do_lock is false (which is now handled in
RestoreStateAndUnlock instead), so both parameters are unnecessary.
Replace calls of PauseAndLock(do_lock=false) with new function
RestoreStateAndUnlock for clarity.
Callers of PauseAndLock ignored the return value when do_lock is
false, so RestoreStateAndUnlock doesn't need to return anything.
RestoreStateAndUnlock was only called with control_adjacent=true. Remove
the parameter and unconditionally call the function that was gated
behind it being true.
CPUManager::PauseAndLock is now only called with do_lock=true, and
unpause_on_unlock only ever was used when do_lock is false (which is now
handled in RestoreStateAndUnlock instead), so both parameters are
unnecessary.
Replace call of CPUManager::PauseAndLock(do_lock=false) with new
function RestoreStateAndUnlock for clarity.
Callers of Core::PauseAndLock ignore the return value when do_lock is
false, so in that case was_unpaused in Core::PauseAndLock doesn't need
to be set and so RestoreStateAndUnlock doesn't need to return anything.
Make s_have_fake_cpu_thread a class member instead. In addition to
getting rid of a bit of static state, this simplifies refactoring in an
upcoming commit.
Don't log a warning in GetPropertyHelper when the property isn't
present. The function returns an optional, so any callers that want to
log a warning when nullopt is returned can do so themselves.
This prevents plugged-in devices (an Xbox One controller in my case)
from spamming the message "W[COMMON]: CM_Get_DevNode_Property returned:
37" twice per second (that value being CR_NO_SUCH_VALUE).
Check if the return value of std::filesystem::remove_all is -1 rather
than 0; the former is the specified return value if there's an error
while 0 just means the directory already didn't exist (which is the end
result we want).
Previously error messages such as the following were possible:
E[COMMON]: DeleteDirRecursively: [path]/User/RedirectSession/ failed The
operation completed successfully.
Also adds a period in the error string to make it look nicer.
Rename m_session to m_last_value_session to better reflect its meaning
and distinguish it from m_current_value_session which will be introduced
in another commit.
Preserve the configured logging verbosity unless the user actually
changes it, rather than capping it to LINFO on release builds.
Rename LogManager::m_level to m_effective_level and distinguish between
the config and effective level in various function/variable names.
Make m_effective_level atomic to prevent data races when setting the
effective log level from the config changed callback.
Avoid creating and then destroying a leaderboard list when game is null,
as doing so causes an access to uninitialized memory due to a bug in
rcheevos.
This can be triggered by starting a game with an invalid or expired
login token.
When opening a file dialog to set the location of a custom path, use the
corresponding user path as the starting location instead of the current
custom path.
When no custom path was set the dialog would be opened with a blank path
which causes Windows (not sure about other platforms) to open the dialog
at the same location where the last dialog was closed, or at the current
working directory if no previous dialog had been opened.
If a nonempty custom path has been set then it has also set the
corresponding user path, so the behavior in that case is unchanged.
Aside from allowing users to persistently set the window to their
desired size, this is also necessary to allow saving of the splitter
positions in FIFOAnalyzer to work correctly.
Make MainWindow::m_fifo_window a unique_ptr to ensure its destructor is
triggered when MainWindow is destroyed.
FIFOPlayerWindow doesn't set MainWindow as its parent in order to
prevent raising MainWindow when focusing FIFOPlayerWindow. This avoids
MainWindow covering up RenderWidget when, e.g., trying to use the object
range feature to pinpoint the index of a particular object.
As a consequence, unlike most QObjects FIFOPlayerWindow wasn't destroyed
when its parent widget was since it didn't have one.
IsolateWasOverwritten and IsolateNotOverwritten share the same basic
logic and have almost exactly the same code, with the only difference
being the comparison function used to keep or discard branches. To avoid
unnecessary code duplication and ensure that the functions stay in sync
after any future changes, create a helper function that takes the
comparison function as a parameter and have IsolateWasOverwritten and
IsolateNotOverwritten call that helper.