Achievement savestate fixes

This commit is contained in:
Henrik Rydgård 2023-07-01 12:31:46 +02:00
parent 01667feccc
commit 9bd67df5b2
11 changed files with 81 additions and 13 deletions

View file

@ -147,6 +147,11 @@ public:
void DoMarker(const char *prevName, u32 arbitraryNumber = 0x42);
void SkipBytes(size_t bytes) {
// Should work in all modes.
*ptr += bytes;
}
size_t Offset() const { return *ptr - ptrStart_; }
private:

View file

@ -85,8 +85,7 @@
#include "sceDmac.h"
#include "sceMp4.h"
#include "sceOpenPSID.h"
#include "../Util/PPGeDraw.h"
#include "Core/Util/PPGeDraw.h"
/*
17: [MIPS32 R4K 00000000 ]: Loader: Type: 1 Vaddr: 00000000 Filesz: 2856816 Memsz: 2856816

View file

@ -354,6 +354,11 @@ static void event_handler_callback(const rc_client_event_t *event, rc_client_t *
}
void Initialize() {
if (!g_Config.bAchievementsEnable) {
_dbg_assert_(!g_rcClient);
INFO_LOG(ACHIEVEMENTS, "Achievements are disabled, not initializing.");
return;
}
_assert_msg_(g_Config.bAchievementsEnable, "Achievements are enabled");
g_challengeMode = true; // the default
@ -453,14 +458,27 @@ void Idle() {
}
void DoState(PointerWrap &p) {
auto sw = p.Section("Achievements", 1);
auto sw = p.Section("Achievements", 0, 1);
if (!sw) {
// Save state is missing the section.
// Reset the runtime.
if (HasAchievementsOrLeaderboards()) {
auto ac = GetI18NCategory(I18NCat::ACHIEVEMENTS);
g_OSD.Show(OSDType::MESSAGE_WARNING, ac->T("Save state loaded without achievement data"), 5.0f);
}
rc_client_reset(g_rcClient);
return;
}
uint32_t data_size = 0;
if (!g_activeGame) {
WARN_LOG(ACHIEVEMENTS, "Save state contained achievement data, but achievements are not active. Ignore.");
Do(p, data_size);
p.SkipBytes(data_size);
return;
}
if (p.mode == PointerWrap::MODE_MEASURE || p.mode == PointerWrap::MODE_WRITE || p.mode == PointerWrap::MODE_VERIFY || p.mode == PointerWrap::MODE_NOOP) {
data_size = (uint32_t)(g_rcClient ? rc_client_progress_size(g_rcClient) : 0);
}
@ -473,18 +491,35 @@ void DoState(PointerWrap &p) {
case PointerWrap::MODE_MEASURE:
case PointerWrap::MODE_WRITE:
case PointerWrap::MODE_VERIFY:
rc_client_serialize_progress(g_rcClient, buffer);
{
int retval = rc_client_serialize_progress(g_rcClient, buffer);
if (retval != RC_OK) {
ERROR_LOG(ACHIEVEMENTS, "Error %d serializing achievement data. Ignoring.", retval);
}
break;
}
}
DoArray(p, buffer, data_size);
switch (p.mode) {
case PointerWrap::MODE_READ:
rc_client_deserialize_progress(g_rcClient, buffer);
{
int retval = rc_client_deserialize_progress(g_rcClient, buffer);
if (retval != RC_OK) {
// TODO: What should we really do here?
ERROR_LOG(ACHIEVEMENTS, "Error %d deserializing achievement data. Ignoring.", retval);
}
break;
}
}
delete[] buffer;
} else {
if (HasAchievementsOrLeaderboards()) {
auto ac = GetI18NCategory(I18NCat::ACHIEVEMENTS);
g_OSD.Show(OSDType::MESSAGE_WARNING, ac->T("Save state loaded without achievement data"), 5.0f);
}
rc_client_reset(g_rcClient);
}
}
@ -610,6 +645,7 @@ void UnloadGame() {
if (g_rcClient) {
rc_client_unload_game(g_rcClient);
}
g_activeGame = false;
}
void change_media_callback(int result, const char *error_message, rc_client_t *client, void *userdata) {

View file

@ -47,6 +47,7 @@
#include "Core/MemMap.h"
#include "Core/MIPS/MIPS.h"
#include "Core/MIPS/JitCommon/JitBlockCache.h"
#include "Core/RetroAchievements.h"
#include "HW/MemoryStick.h"
#include "GPU/GPUState.h"
@ -391,6 +392,7 @@ namespace SaveState
currentMIPS->DoState(p);
HLEDoState(p);
__KernelDoState(p);
Achievements::DoState(p);
// Kernel object destructors might close open files, so do the filesystem last.
pspFileSystem.DoState(p);
}

View file

@ -196,7 +196,9 @@ void RetroAchievementsSettingsScreen::CreateAccountTab(UI::ViewGroup *viewGroup)
using namespace UI;
if (Achievements::IsLoggedIn()) {
if (!g_Config.bAchievementsEnable) {
viewGroup->Add(new TextView(ac->T("Achievements are disabled")));
} else if (Achievements::IsLoggedIn()) {
const rc_client_user_t *info = rc_client_get_user_info(Achievements::GetClient());
// In the future, RetroAchievements will support display names. Prepare for that.
@ -255,9 +257,14 @@ void RetroAchievementsSettingsScreen::CreateSettingsTab(UI::ViewGroup *viewGroup
using namespace UI;
viewGroup->Add(new ItemHeader(ac->T("Settings")));
viewGroup->Add(new CheckBox(&g_Config.bAchievementsRichPresence, ac->T("Rich Presence")));
viewGroup->Add(new CheckBox(&g_Config.bAchievementsSoundEffects, ac->T("Sound Effects"))); // not yet implemented
viewGroup->Add(new CheckBox(&g_Config.bAchievementsLogBadMemReads, ac->T("Log bad memory accesses")));
viewGroup->Add(new CheckBox(&g_Config.bAchievementsEnable, ac->T("Achievements enabled")))->OnClick.Add([&](UI::EventParams &e) -> UI::EventReturn {
Achievements::UpdateSettings();
RecreateViews();
return UI::EVENT_DONE;
});
viewGroup->Add(new CheckBox(&g_Config.bAchievementsRichPresence, ac->T("Rich Presence")))->SetEnabledPtr(&g_Config.bAchievementsEnable);
viewGroup->Add(new CheckBox(&g_Config.bAchievementsSoundEffects, ac->T("Sound Effects")))->SetEnabledPtr(&g_Config.bAchievementsEnable); // not yet implemented
viewGroup->Add(new CheckBox(&g_Config.bAchievementsLogBadMemReads, ac->T("Log bad memory accesses")))->SetEnabledPtr(&g_Config.bAchievementsEnable);
// Not yet fully implemented
// viewGroup->Add(new CheckBox(&g_Config.bAchievementsChallengeMode, ac->T("Challenge Mode (no savestates)")));

View file

@ -106,6 +106,9 @@
<ClInclude Include="Theme.h" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Core\Core.vcxproj">
<Project>{533f1d30-d04d-47cc-ad71-20f658907e36}</Project>
</ProjectReference>
<ProjectReference Include="..\ext\discord-rpc-build\discord-rpc.vcxproj">
<Project>{beb0a821-3c7f-410f-a525-63afbc69bf8f}</Project>
</ProjectReference>

View file

@ -26,6 +26,7 @@
%d achievements, %d points = %d achievements, %d points
Account = Account
Achievements = Achievements
Achievements are disabled = Achievements are disabled
Challenge Mode = Challenge Mode
Challenge Mode (no savestates) = Challenge Mode (no savestates)
Earned = You have earned %d of %d achievements, and %d of %d points
@ -33,7 +34,6 @@ How to use RetroAchievements = How to use RetroAchievements
Leaderboard submission is enabled = Leaderboard submission is enabled
Leaderboards = Leaderboards
Links = Links
Local = Local
Locked achievements = Locked achievements
Log bad memory accesses = Log bad memory accesses
Mastered %1 = Mastered %1
@ -41,6 +41,7 @@ Register on www.retroachievements.org = Register on www.retroachievements.org
RetroAchievements are not available for this game = RetroAchievements are not available for this game
RetroAchievements website = RetroAchievements website
Rich Presence = Rich Presence
Save state loaded without achievement data = Save state loaded without achievement data
Sound Effects = Sound Effects
Statistics = Statistics
Submitted Score = Submitted Score

View file

@ -143,6 +143,12 @@ void System_AudioGetDebugStats(char *buf, size_t bufSize) { if (buf) buf[0] = '\
void System_AudioClear() {}
void System_AudioPushSamples(const s32 *audio, int numSamples) {}
// TODO: To avoid having to define these here, these should probably be turned into system "requests".
void NativeSaveSecret(const char *nameOfSecret, const std::string &data) {}
std::string NativeLoadSecret(const char *nameOfSecret) {
return "";
}
int printUsage(const char *progname, const char *reason)
{
if (reason != NULL)

View file

@ -508,6 +508,9 @@
<ProjectReference Include="..\ext\libzstd.vcxproj">
<Project>{8bfd8150-94d5-4bf9-8a50-7bd9929a0850}</Project>
</ProjectReference>
<ProjectReference Include="..\ext\rcheevos-build\rcheevos.vcxproj">
<Project>{31694510-a8c0-40f6-b09b-e8df825adefa}</Project>
</ProjectReference>
<ProjectReference Include="..\GPU\GPU.vcxproj">
<Project>{457f45d2-556f-47bc-a31d-aff0d15beaed}</Project>
</ProjectReference>

View file

@ -103,6 +103,12 @@ void System_AudioGetDebugStats(char *buf, size_t bufSize) { if (buf) buf[0] = '\
void System_AudioClear() {}
void System_AudioPushSamples(const s32 *audio, int numSamples) {}
// TODO: To avoid having to define these here, these should probably be turned into system "requests".
void NativeSaveSecret(const char *nameOfSecret, const std::string &data) {}
std::string NativeLoadSecret(const char *nameOfSecret) {
return "";
}
#if PPSSPP_PLATFORM(ANDROID)
JNIEnv *getEnv() {
return nullptr;

View file

@ -426,15 +426,15 @@
<ProjectReference Include="..\ext\libzstd.vcxproj">
<Project>{8bfd8150-94d5-4bf9-8a50-7bd9929a0850}</Project>
</ProjectReference>
<ProjectReference Include="..\ext\rcheevos-build\rcheevos.vcxproj">
<Project>{31694510-a8c0-40f6-b09b-e8df825adefa}</Project>
</ProjectReference>
<ProjectReference Include="..\ext\zlib\zlib.vcxproj">
<Project>{f761046e-6c38-4428-a5f1-38391a37bb34}</Project>
</ProjectReference>
<ProjectReference Include="..\GPU\GPU.vcxproj">
<Project>{457f45d2-556f-47bc-a31d-aff0d15beaed}</Project>
</ProjectReference>
<ProjectReference Include="..\UI\UI.vcxproj">
<Project>{004b8d11-2be3-4bd9-ab40-2be04cf2096f}</Project>
</ProjectReference>
</ItemGroup>
<ItemGroup>
<ClInclude Include="JitHarness.h" />