Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

RetroAchievements - Improved Game Loading #12216

Merged

Conversation

LillyJadeKatrin
Copy link
Contributor

The changes in this PR are for improving when and how the AchievementManager loads games so it can properly protect against players switching apps and opening homebrews while properly allowing multi-disc or multi-file support. This will happen by calculating a new hash whenever the currently playing media changes, and shutting down the AchievementManager* if the new hash does not reference the same game as the previous hash.

*This does not load a new game, this closes the AchievementManager entirely and it will not be reopened until all games are closed and a new boot is performed.

@LillyJadeKatrin
Copy link
Contributor Author

This PR is still in progress and more commits will be added as work on this continues.

@AdmiralCurtiss AdmiralCurtiss marked this pull request as draft October 1, 2023 17:40
Copy link
Member

@JosJuice JosJuice left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Am I missing something, or is the hashing not actually async?

Source/Core/Core/AchievementManager.h Outdated Show resolved Hide resolved
@LillyJadeKatrin
Copy link
Contributor Author

Am I missing something, or is the hashing not actually async?

Ah, the network calls are but the hash calculation is not, good point - I'll move that to the queue.

@LillyJadeKatrin LillyJadeKatrin force-pushed the retroachievements-rehash branch 13 times, most recently from 49d3f03 to 345b49e Compare October 3, 2023 11:42
@LillyJadeKatrin LillyJadeKatrin marked this pull request as ready for review October 3, 2023 12:00
Source/Core/Core/AchievementManager.cpp Outdated Show resolved Hide resolved
Source/Core/Core/AchievementManager.cpp Outdated Show resolved Hide resolved
Source/Core/Core/AchievementManager.cpp Outdated Show resolved Hide resolved
Source/Core/Core/Boot/Boot.cpp Outdated Show resolved Hide resolved
Source/Core/Core/IOS/ES/ES.cpp Outdated Show resolved Hide resolved
Source/Core/Core/AchievementManager.cpp Show resolved Hide resolved
Source/Core/Core/AchievementManager.cpp Outdated Show resolved Hide resolved
@LillyJadeKatrin LillyJadeKatrin force-pushed the retroachievements-rehash branch 3 times, most recently from f15e1c1 to 8ee76a8 Compare October 4, 2023 05:23
Source/Core/Core/AchievementManager.cpp Outdated Show resolved Hide resolved
Source/Core/Core/AchievementManager.cpp Outdated Show resolved Hide resolved
Source/Core/Core/AchievementManager.cpp Outdated Show resolved Hide resolved
Source/Core/Core/AchievementManager.cpp Outdated Show resolved Hide resolved
@LillyJadeKatrin LillyJadeKatrin force-pushed the retroachievements-rehash branch 3 times, most recently from 994ba47 to b927895 Compare October 5, 2023 05:12
@LillyJadeKatrin LillyJadeKatrin force-pushed the retroachievements-rehash branch 4 times, most recently from 091fa6d to ba54de2 Compare October 20, 2023 01:11
Source/Core/Core/AchievementManager.h Outdated Show resolved Hide resolved
@@ -814,8 +988,7 @@ AchievementManager::ResponseType AchievementManager::VerifyCredentials(const std
return r_type;
}

AchievementManager::ResponseType
AchievementManager::ResolveHash(std::array<char, HASH_LENGTH> game_hash)
AchievementManager::ResponseType AchievementManager::ResolveHash(Hash game_hash, u32* game_id)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A bit tangential, but:

Suggested change
AchievementManager::ResponseType AchievementManager::ResolveHash(Hash game_hash, u32* game_id)
AchievementManager::ResponseType AchievementManager::ResolveHash(const Hash& game_hash, u32* game_id)

would avoid an unnecessary copy.

Also maybe just use a struct for the return value instead of an out pointer, since you can just do:

const auto [response, new_game_id] = ResolveHash(current_hash);

which would be a little more straightforward and make the sanitizing behavior completely handled by the function, rather than relying on initializing the value at the point of the call (i.e. consider a refactor, where the initialization for the variable pointed to gets removed. with the current code, this would cause an uninitialized read in one path, whereas a return value prevents that from happening entirely)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this a change you feel I should make across the board? Because that's a lot and probably should go in a separate PR if so.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@lioncash Would still like your opinion on this, many thanks.

@LillyJadeKatrin LillyJadeKatrin force-pushed the retroachievements-rehash branch 2 times, most recently from c7f8178 to 9f886cf Compare November 10, 2023 03:59
Copy link
Contributor

@AdmiralCurtiss AdmiralCurtiss left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Your commit history here is bad, there's a few issues that you introduce in one commit only to fix it in a later one. Please clean that up.

Source/Core/Core/AchievementManager.h Outdated Show resolved Hide resolved
Source/Core/Core/AchievementManager.cpp Outdated Show resolved Hide resolved
Source/Core/Core/AchievementManager.cpp Show resolved Hide resolved
Source/Core/Core/AchievementManager.cpp Outdated Show resolved Hide resolved

const auto start_session_response = StartRASession();
if (start_session_response != ResponseType::SUCCESS)
m_loading_volume = DiscIO::CreateVolume(volume->GetBlobReader().CopyReader());
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This entire construct makes me sad but I don't have any better ideas either with the currently available functions in rcheevos.

Source/Core/Core/AchievementManager.cpp Outdated Show resolved Hide resolved
Source/Core/Core/AchievementManager.cpp Outdated Show resolved Hide resolved
Source/Core/Core/AchievementManager.cpp Outdated Show resolved Hide resolved
Source/Core/Core/AchievementManager.cpp Outdated Show resolved Hide resolved
@LillyJadeKatrin LillyJadeKatrin force-pushed the retroachievements-rehash branch 2 times, most recently from 5553282 to 7ce7222 Compare November 21, 2023 03:12
@LillyJadeKatrin
Copy link
Contributor Author

Your commit history here is bad, there's a few issues that you introduce in one commit only to fix it in a later one. Please clean that up.

I think I got all of these? Let me know if I've missed anything.

@LillyJadeKatrin LillyJadeKatrin force-pushed the retroachievements-rehash branch 5 times, most recently from 19d88e8 to 72b9640 Compare November 23, 2023 22:10
@AdmiralCurtiss
Copy link
Contributor

Untested but yeah this looks good now.

Source/Core/Core/AchievementManager.cpp Outdated Show resolved Hide resolved
Source/Core/Core/AchievementManager.cpp Outdated Show resolved Hide resolved
Source/Core/Core/AchievementManager.cpp Outdated Show resolved Hide resolved
Source/Core/Core/AchievementManager.cpp Outdated Show resolved Hide resolved
Source/Core/Core/AchievementManager.cpp Outdated Show resolved Hide resolved
Source/Core/Core/AchievementManager.cpp Outdated Show resolved Hide resolved
Source/Core/Core/AchievementManager.cpp Outdated Show resolved Hide resolved
This change splits LoadGameAsync into three methods: two HashGame methods to accept either a string filepath or a volume, and a common LoadGameSync that both HashGames call to actually process the code. In the process, some minor cleanup, and the hash resolution now takes place on the work queue asynchronously.
The Disabled state sits between Game Closed and completely Shutdown - stronger than the former, as it refuses to let a game be opened again until AchievementManager is restored (which only happens upon a fresh core boot) but it isn't completely shut down and will still allow the player to be logged in and access the achievement settings and their (global) achievement header.
If the new game ID is a different title than the previous game ID, the achievement manager is compromised.
@lioncash lioncash merged commit b427604 into dolphin-emu:master Dec 5, 2023
11 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
4 participants