I've gone through all relevant settings for Rogue Squadron II and III
and overhauled their game INI files. Each setting is explained with a
comment.
Some settings I chose not to include:
* EFB to RAM only seems to affect certain fadeouts in Rogue Squadron II.
Without it, the affected fadeouts are replaced by a pure black screen.
I don't think this is important enough to warrant the performance hit.
* As I was unable to find anything Rogue Squadron III needs EFB to RAM
for, I also didn't find anything it needs DeferEFBCopies disabled for.
* I didn't find anything EFBEmulateFormatChanges was needed for in
either game.
* Enabling EFB access makes the ship engine glow visible in Rogue
Squadron III, but this effect is minor enough that you probably won't
notice it's missing unless you know it's supposed to be there. Since
this is Dolphin's heaviest game, let's give users the choice.
* I was considering forcing XFB to RAM for Rogue Squadron III to make
fadeouts render properly instead of going from magenta to black, since
enabling XFB to RAM doesn't really hurt performance when you're
already enabling EFB to RAM. But then I was unable to find a reason
why we should enable EFB to RAM for this game.
Tested in RS2 and RS3. The RS3 demo disc settings are copied from the
RS3 settings and haven't been tested by me.
Previously, when an input device was connected or disconnected, we would
recreate all devices. This commit makes it so we only touch the relevant
device instead. This matters because recreating a device causes us to
drop all held buttons for that device. Due to Android only delivering
inputs as events, we're unable to poll for currently held buttons when
recreating a device.
This recently became a problem for users of Ayn devices due to a
firmware update. Every now and then, something about the display
viewports changes, triggering an update to an input device that I assume
is a touch input device. This input device isn't something users
normally map in Dolphin's controller settings, but it changing was
causing Dolphin to drop all held buttons for the device's built-in
gamepad as well as any other connected gamepads.
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.
In the unit test I'm adding in the next commit, I want to call
MemoryManager::Init, but initializing all the hardware that
MemoryManager::InitMMIO calls into would be cumbersome.
Calling MemoryManager::InitMMIO from MemoryManager::Init was a bit
strange anyway. Because MemoryManager::Init is called about halfway
through HW::Init, some of the hardware that MemoryManager::InitMMIO
calls into isn't initialized yet.
Most systems that Dolphin runs on have a page size of 4 KiB, which
conveniently matches the page size of the GameCube and Wii. But there
are also systems that use larger page sizes, notably Apple CPUs with
16 KiB page sizes. To let us create host mappings on such systems, this
commit implements combining guest mappings into host page sized mappings
wherever possible.
For this to work for a given mapping, not only do four (in the case of
16 KiB) guest mappings have to exist adjacent to each other, but the
corresponding translated addresses also have to be adjacent, and the
lowest bits of the addresses have to match. When I tested a few games,
the following percentages of guest mappings met these criteria:
Spider-Man 2: 0%-12%
Rogue Squadron 2: 39%-42%
Rogue Squadron 3: 28%-41%
So while 16 KiB systems don't get as much of a performance improvement
as 4 KiB systems, they do still get some improvement.
Removing and readding every page table mapping every time something
changes in the page table is very slow. Instead, let's generate a diff
and ask Memmap to update only the diff.
Page table mappings are only used when DR is set, so if page tables are
updated when DR isn't set, we can wait with updating page table mappings
until DR gets set. This lets us batch page table updates in the Disney
Trio of Destruction, improving performance when the games are loading
data. It doesn't help much for GameCube games, because those run tlbie
with DR set.
The PowerPCState struct has had its members slightly reordered. I had to
put pagetable_update_pending less than 4 KiB from the start so AArch64's
LDRB (immediate) can access it, and I also took the opportunity to move
some other members around to cut down on padding.
Previously we've only been setting up fastmem mappings for block address
translation, but now we also do it for page address translation. This
increases performance when games access memory using page tables, but
decreases performance when games set up page tables.
The tlbie instruction is used as an indication that the mappings need to
be updated.
There are some accuracy downsides:
* The TLB is now effectively infinitely large, which matters if games
don't use tlbie when modifying page tables.
* The R and C bits for page table entries get set pessimistically rather
than when the page is actually accessed.
No games are known to be broken by these inaccuracies, but unfortunately
the second inaccuracy causes a large performance regression in Rogue
Squadron 3. You still get the old, more accurate behavior if Enable
Write-Back Cache is on.
It turns out that it is possible to create a login alias in RetroAchievements
such that you can log in with a username that doesn't match your display name.
AchievementManager was treating this as a synchronization error, but this is
desired behavior, so this removes the check.
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.