Implement RetroAchievements challenge mode restrictions, and fix related bugs

This commit is contained in:
Henrik Rydgård committed 2023-07-08 21:55:32 +02:00
1 parent 9e4387c529
commit c17b84b3d4
13 files changed
+192 -112

No files matched your search

+1 -1
View File
@@ -5,6 +5,7 @@
#include <functional>
#include <vector>
#include "Common/Data/Collections/FastVec.h"
#include "Common/GPU/Vulkan/VulkanContext.h"
#include "Common/GPU/GPUBackendCommon.h"
@@ -205,4 +206,3 @@ private:
uint32_t usage_ = 0;
bool grow_;
};
+14 -1
View File
@@ -2,6 +2,7 @@
#include "Common/System/OSD.h"
#include "Common/TimeUtil.h"
#include "Common/Log.h"
OnScreenDisplay g_OSD;
@@ -146,6 +147,11 @@ void OnScreenDisplay::ShowChallengeIndicator(int achievementID, bool show) {
}
}
if (!show) {
// Sanity check
return;
}
// OK, let's make a new side-entry.
Entry entry;
entry.numericID = achievementID;
@@ -172,13 +178,20 @@ void OnScreenDisplay::ShowLeaderboardTracker(int leaderboardTrackerID, const cha
}
}
if (!show) {
// Sanity check
return;
}
// OK, let's make a new side-entry.
Entry entry;
entry.numericID = leaderboardTrackerID;
entry.type = OSDType::LEADERBOARD_TRACKER;
entry.startTime = now;
entry.endTime = now + 10000000.0; // Don't auto-fadeout
entry.text = trackerText;
if (trackerText) {
entry.text = trackerText;
}
sideEntries_.insert(sideEntries_.begin(), entry);
}
-1
View File
@@ -266,7 +266,6 @@ static bool DefaultSasThread() {
static const ConfigSetting achievementSettings[] = {
ConfigSetting("AchievementsEnable", &g_Config.bAchievementsEnable, true, CfgFlag::DEFAULT),
ConfigSetting("AchievementsRichPresence", &g_Config.bAchievementsRichPresence, true, CfgFlag::DEFAULT),
ConfigSetting("AchievementsChallengeMode", &g_Config.bAchievementsChallengeMode, false, CfgFlag::DEFAULT),
ConfigSetting("AchievementsEncoreMode", &g_Config.bAchievementsEncoreMode, false, CfgFlag::DEFAULT),
ConfigSetting("AchievementsUnofficial", &g_Config.bAchievementsUnofficial, false, CfgFlag::DEFAULT),
-1
View File
@@ -488,7 +488,6 @@ public:
// Retro Achievement settings
// Copied from Duckstation, we might want to remove some.
bool bAchievementsEnable;
bool bAchievementsRichPresence;
bool bAchievementsChallengeMode;
bool bAchievementsEncoreMode;
bool bAchievementsUnofficial;
+10 -4
View File
@@ -19,6 +19,7 @@
#include "Core/System.h"
#include "Core/HLE/sceCtrl.h"
#include "Core/MIPS/JitCommon/JitCommon.h"
#include "Core/RetroAchievements.h"
#include "GPU/Common/PostShader.h"
#ifdef _WIN32
@@ -319,9 +320,11 @@ void __CheatDoState(PointerWrap &p) {
}
void hleCheat(u64 userdata, int cyclesLate) {
if (cheatsEnabled != g_Config.bEnableCheats) {
bool shouldBeEnabled = !Achievements::ChallengeModeActive() && g_Config.bEnableCheats;
if (cheatsEnabled != shouldBeEnabled) {
// Okay, let's move to the desired state, then.
if (g_Config.bEnableCheats) {
if (shouldBeEnabled) {
__CheatStart();
} else {
__CheatStop();
@@ -1193,6 +1196,10 @@ void CWCheatEngine::ExecuteOp(const CheatOperation &op, const CheatCode &cheat,
}
void CWCheatEngine::Run() {
if (Achievements::ChallengeModeActive()) {
return;
}
for (CheatCode cheat : cheats_) {
// InterpretNextOp and ExecuteOp move i.
for (size_t i = 0; i < cheat.lines.size(); ) {
@@ -1207,8 +1214,7 @@ bool CWCheatEngine::HasCheats() {
}
bool CheatsInEffect() {
if (!cheatEngine || !cheatsEnabled)
if (!cheatEngine || !cheatsEnabled || Achievements::ChallengeModeActive())
return false;
return cheatEngine->HasCheats();
}
+10 -6
View File
@@ -49,6 +49,7 @@
#include "Core/HLE/sceKernelInterrupt.h"
#include "Core/HW/Display.h"
#include "Core/Util/PPGeDraw.h"
#include "Core/RetroAchievements.h"
#include "GPU/GPU.h"
#include "GPU/GPUState.h"
@@ -348,12 +349,15 @@ void __DisplaySetWasPaused() {
}
static int FrameTimingLimit() {
if (PSP_CoreParameter().fpsLimit == FPSLimit::CUSTOM1)
return g_Config.iFpsLimit1;
if (PSP_CoreParameter().fpsLimit == FPSLimit::CUSTOM2)
return g_Config.iFpsLimit2;
if (PSP_CoreParameter().fpsLimit == FPSLimit::ANALOG)
return PSP_CoreParameter().analogFpsLimit;
if (!Achievements::ChallengeModeActive()) {
if (PSP_CoreParameter().fpsLimit == FPSLimit::CUSTOM1)
return g_Config.iFpsLimit1;
if (PSP_CoreParameter().fpsLimit == FPSLimit::CUSTOM2)
return g_Config.iFpsLimit2;
if (PSP_CoreParameter().fpsLimit == FPSLimit::ANALOG)
return PSP_CoreParameter().analogFpsLimit;
}
// Note: Fast-forward is OK in challenge mode.
if (PSP_CoreParameter().fastForward)
return 0;
return framerate;
+32 -23
View File
@@ -74,8 +74,6 @@ namespace Achievements {
// It's the name of the secret, not a secret name - the value is not secret :)
static const char *RA_TOKEN_SECRET_NAME = "retroachievements";
static u32 GetGameID();
static Achievements::Statistics g_stats;
const std::string g_gameIconCachePrefix = "game:";
@@ -84,8 +82,6 @@ const std::string g_iconCachePrefix = "badge:";
Path s_game_path;
std::string s_game_hash;
bool g_challengeMode = true;
bool g_isIdentifying = false;
// rc_client implementation
@@ -101,10 +97,6 @@ bool IsLoggedIn() {
return rc_client_get_user_info(g_rcClient) != nullptr;
}
bool ChallengeModeActive() {
return g_challengeMode;
}
bool EncoreModeActive() {
if (!g_rcClient) {
return false;
@@ -119,15 +111,33 @@ bool UnofficialEnabled() {
return rc_client_get_unofficial_enabled(g_rcClient);
}
bool IsActive() {
return GetGameID() != 0;
bool ChallengeModeActive() {
if (!g_rcClient) {
return false;
}
return rc_client_get_hardcore_enabled(g_rcClient);
}
bool WarnUserIfChallengeModeActive(const char *message) {
if (!ChallengeModeActive()) {
return false;
}
const char *showMessage = message;
if (!message) {
auto ac = GetI18NCategory(I18NCat::ACHIEVEMENTS);
showMessage = ac->T("This feature is not available in Challenge Mode");
}
g_OSD.Show(OSDType::MESSAGE_WARNING, showMessage, 3.0f);
return true;
}
bool IsBlockingExecution() {
return g_isIdentifying;
}
u32 GetGameID() {
static u32 GetGameID() {
if (!g_rcClient) {
return 0;
}
@@ -139,6 +149,10 @@ u32 GetGameID() {
return info->id; // 0 if not identified
}
bool IsActive() {
return GetGameID() != 0;
}
// This is the function the rc_client will use to read memory for the emulator. we don't need it yet,
// so just provide a dummy function that returns "no memory read".
static uint32_t read_memory_callback(uint32_t address, uint8_t *buffer, uint32_t num_bytes, rc_client_t *client) {
@@ -260,12 +274,12 @@ static void event_handler_callback(const rc_client_event_t *event, rc_client_t *
break;
case RC_CLIENT_EVENT_LEADERBOARD_FAILED:
NOTICE_LOG(ACHIEVEMENTS, "Leaderboard attempt failed: %s", event->leaderboard->title);
g_OSD.Show(OSDType::MESSAGE_INFO, ReplaceAll(ac->T("%1: Failed"), "%1", event->leaderboard->title), 3.0f);
g_OSD.Show(OSDType::MESSAGE_INFO, ReplaceAll(ac->T("%1: Leaderboard attempt failed"), "%1", event->leaderboard->title), 3.0f);
// A leaderboard attempt has failed.
break;
case RC_CLIENT_EVENT_LEADERBOARD_SUBMITTED:
NOTICE_LOG(ACHIEVEMENTS, "Leaderboard result submitted: %s", event->leaderboard->title);
g_OSD.Show(OSDType::MESSAGE_SUCCESS, ReplaceAll(ac->T("%1: Submitting successful score!"), "%1", event->leaderboard->title), event->leaderboard->description, 3.0f);
g_OSD.Show(OSDType::MESSAGE_SUCCESS, ReplaceAll(ReplaceAll(ac->T("%1: Submitting leaderboard score: %2!"), "%1", event->leaderboard->title), "%2", event->leaderboard->tracker_value), event->leaderboard->description, 3.0f);
// A leaderboard attempt was completed.The handler may show a message with the leaderboard title and /or description indicating the final value being submitted to the server.
break;
case RC_CLIENT_EVENT_ACHIEVEMENT_CHALLENGE_INDICATOR_SHOW:
@@ -288,7 +302,7 @@ static void event_handler_callback(const rc_client_event_t *event, rc_client_t *
g_OSD.ShowAchievementProgress(event->achievement->id, 2.0f);
break;
case RC_CLIENT_EVENT_LEADERBOARD_TRACKER_SHOW:
NOTICE_LOG(ACHIEVEMENTS, "Leaderboard tracker show: %s", event->leaderboard_tracker->display);
NOTICE_LOG(ACHIEVEMENTS, "Leaderboard tracker show: '%s' (id %d)", event->leaderboard_tracker->display, event->leaderboard_tracker->id);
// A leaderboard_tracker has become active. The handler should show the tracker text on screen.
// Multiple active leaderboards may share a single tracker if they have the same definition and value.
// As such, the leaderboard tracker IDs are unique amongst the leaderboard trackers, and have no correlation to the active leaderboard(s).
@@ -297,13 +311,13 @@ static void event_handler_callback(const rc_client_event_t *event, rc_client_t *
break;
case RC_CLIENT_EVENT_LEADERBOARD_TRACKER_HIDE:
// A leaderboard_tracker has become inactive. The handler should hide the tracker text from the screen.
NOTICE_LOG(ACHIEVEMENTS, "Leaderboard tracker hide: %s", event->leaderboard_tracker->display);
NOTICE_LOG(ACHIEVEMENTS, "Leaderboard tracker hide: '%s' (id %d)", event->leaderboard_tracker->display, event->leaderboard_tracker->id);
g_OSD.ShowLeaderboardTracker(event->leaderboard_tracker->id, nullptr, false);
break;
case RC_CLIENT_EVENT_LEADERBOARD_TRACKER_UPDATE:
// A leaderboard_tracker value has been updated. The handler should update the tracker text on the screen.
NOTICE_LOG(ACHIEVEMENTS, "Leaderboard tracker update: %s", event->leaderboard_tracker->display);
g_OSD.ShowLeaderboardTracker(event->leaderboard_tracker->id, event->leaderboard_tracker->display, false);
NOTICE_LOG(ACHIEVEMENTS, "Leaderboard tracker update: '%s' (id %d)", event->leaderboard_tracker->display, event->leaderboard_tracker->id);
g_OSD.ShowLeaderboardTracker(event->leaderboard_tracker->id, event->leaderboard_tracker->display, true);
break;
case RC_CLIENT_EVENT_RESET:
WARN_LOG(ACHIEVEMENTS, "Resetting game due to achievement setting change!");
@@ -328,16 +342,10 @@ void Initialize() {
}
_assert_msg_(g_Config.bAchievementsEnable, "Achievements are enabled");
g_challengeMode = true; // the default
g_rcClient = rc_client_create(read_memory_callback, server_call_callback);
// Provide a logging function to simplify debugging
rc_client_enable_logging(g_rcClient, RC_CLIENT_LOG_LEVEL_VERBOSE, log_message_callback);
// FOR NOW: Disable hardcore - if we goof something up in the implementation, we don't want our
// account disabled for cheating.
rc_client_set_hardcore_enabled(g_rcClient, 0);
g_challengeMode = false;
// Disable SSL for now.
rc_client_set_host(g_rcClient, "http://retroachievements.org");
@@ -590,6 +598,7 @@ void SetGame(const Path &path) {
g_isIdentifying = true;
// Apply pre-load settings.
rc_client_set_hardcore_enabled(g_rcClient, g_Config.bAchievementsChallengeMode ? 1 : 0);
rc_client_set_encore_mode_enabled(g_rcClient, g_Config.bAchievementsEncoreMode ? 1 : 0);
rc_client_set_unofficial_enabled(g_rcClient, g_Config.bAchievementsUnofficial ? 1 : 0);
+13 -3
View File
@@ -51,14 +51,24 @@ bool IsLoggedIn();
// Returns true if in a game, and achievements are active in the current game.
bool IsActive();
// Returns true if unofficial achievements are enabled.
bool UnofficialEnabled();
// Returns true if the emulator should hold off on executing game code, such as during game identification.
bool IsBlockingExecution();
/// Returns true if features such as save states should be disabled.
// Returns true if features such as save states should be disabled.
// This should only be used for controlling functionality of the following things, which are banned in Challenge/Hardcore mode:
//
// * Savestates
// * Slowdown time (though hard to fully prevent, could use crazy post shaders or software rendering...)
bool ChallengeModeActive();
// Returns true if unofficial achievements are enabled.
bool UnofficialEnabled();
// Same as ChallengeModeActive but comes with a convenient user message. Don't use for every-frame checks or UI enablement,
// only for shortcut keys and commands. You should look up the message in I18NCat::ACHIEVEMENTS.
// If no message is specified, a standard "This feature is not available in Challenge Mode" message will be shown.
// Also returns true if challenge mode is active.
bool WarnUserIfChallengeModeActive(const char *message = nullptr);
// The new API is so much nicer that we can use it directly instead of wrapping it. So let's expose the client.
// Will of course return nullptr if not active.
+5
View File
@@ -399,6 +399,11 @@ namespace SaveState
void Enqueue(SaveState::Operation op)
{
if (Achievements::ChallengeModeActive()) {
// No savestate operations are permitted, let's just ignore it.
return;
}
std::lock_guard<std::mutex> guard(mutex);
pending.push_back(op);
+37 -31
View File
@@ -582,7 +582,7 @@ void EmuScreen::onVKey(int virtualKeyCode, bool down) {
break;
case VIRTKEY_SPEED_TOGGLE:
if (down) {
if (down && !Achievements::WarnUserIfChallengeModeActive()) {
// Cycle through enabled speeds.
if (PSP_CoreParameter().fpsLimit == FPSLimit::NORMAL && g_Config.iFpsLimit1 >= 0) {
PSP_CoreParameter().fpsLimit = FPSLimit::CUSTOM1;
@@ -598,28 +598,32 @@ void EmuScreen::onVKey(int virtualKeyCode, bool down) {
break;
case VIRTKEY_SPEED_CUSTOM1:
if (down) {
if (PSP_CoreParameter().fpsLimit == FPSLimit::NORMAL) {
PSP_CoreParameter().fpsLimit = FPSLimit::CUSTOM1;
g_OSD.Show(OSDType::MESSAGE_INFO, sc->T("fixed", "Speed: alternate"), 1.0);
}
} else {
if (PSP_CoreParameter().fpsLimit == FPSLimit::CUSTOM1) {
PSP_CoreParameter().fpsLimit = FPSLimit::NORMAL;
g_OSD.Show(OSDType::MESSAGE_INFO, sc->T("standard", "Speed: standard"), 1.0);
if (!Achievements::WarnUserIfChallengeModeActive()) {
if (down) {
if (PSP_CoreParameter().fpsLimit == FPSLimit::NORMAL) {
PSP_CoreParameter().fpsLimit = FPSLimit::CUSTOM1;
g_OSD.Show(OSDType::MESSAGE_INFO, sc->T("fixed", "Speed: alternate"), 1.0);
}
} else {
if (PSP_CoreParameter().fpsLimit == FPSLimit::CUSTOM1) {
PSP_CoreParameter().fpsLimit = FPSLimit::NORMAL;
g_OSD.Show(OSDType::MESSAGE_INFO, sc->T("standard", "Speed: standard"), 1.0);
}
}
}
break;
case VIRTKEY_SPEED_CUSTOM2:
if (down) {
if (PSP_CoreParameter().fpsLimit == FPSLimit::NORMAL) {
PSP_CoreParameter().fpsLimit = FPSLimit::CUSTOM2;
g_OSD.Show(OSDType::MESSAGE_INFO, sc->T("SpeedCustom2", "Speed: alternate 2"), 1.0);
}
} else {
if (PSP_CoreParameter().fpsLimit == FPSLimit::CUSTOM2) {
PSP_CoreParameter().fpsLimit = FPSLimit::NORMAL;
g_OSD.Show(OSDType::MESSAGE_INFO, sc->T("standard", "Speed: standard"), 1.0);
if (!Achievements::WarnUserIfChallengeModeActive()) {
if (down) {
if (PSP_CoreParameter().fpsLimit == FPSLimit::NORMAL) {
PSP_CoreParameter().fpsLimit = FPSLimit::CUSTOM2;
g_OSD.Show(OSDType::MESSAGE_INFO, sc->T("SpeedCustom2", "Speed: alternate 2"), 1.0);
}
} else {
if (PSP_CoreParameter().fpsLimit == FPSLimit::CUSTOM2) {
PSP_CoreParameter().fpsLimit = FPSLimit::NORMAL;
g_OSD.Show(OSDType::MESSAGE_INFO, sc->T("standard", "Speed: standard"), 1.0);
}
}
}
break;
@@ -635,13 +639,15 @@ void EmuScreen::onVKey(int virtualKeyCode, bool down) {
break;
case VIRTKEY_FRAME_ADVANCE:
if (down) {
// If game is running, pause emulation immediately. Otherwise, advance a single frame.
if (Core_IsStepping()) {
frameStep_ = true;
Core_EnableStepping(false);
} else if (!frameStep_) {
Core_EnableStepping(true, "ui.frameAdvance", 0);
if (!Achievements::WarnUserIfChallengeModeActive()) {
if (down) {
// If game is running, pause emulation immediately. Otherwise, advance a single frame.
if (Core_IsStepping()) {
frameStep_ = true;
Core_EnableStepping(false);
} else if (!frameStep_) {
Core_EnableStepping(true, "ui.frameAdvance", 0);
}
}
}
break;
@@ -691,7 +697,7 @@ void EmuScreen::onVKey(int virtualKeyCode, bool down) {
#endif
case VIRTKEY_REWIND:
if (down) {
if (down && !Achievements::WarnUserIfChallengeModeActive()) {
if (SaveState::CanRewind()) {
SaveState::Rewind(&AfterSaveStateAction);
} else {
@@ -700,21 +706,21 @@ void EmuScreen::onVKey(int virtualKeyCode, bool down) {
}
break;
case VIRTKEY_SAVE_STATE:
if (down)
if (down && !Achievements::WarnUserIfChallengeModeActive())
SaveState::SaveSlot(gamePath_, g_Config.iCurrentStateSlot, &AfterSaveStateAction);
break;
case VIRTKEY_LOAD_STATE:
if (down)
if (down && !Achievements::WarnUserIfChallengeModeActive())
SaveState::LoadSlot(gamePath_, g_Config.iCurrentStateSlot, &AfterSaveStateAction);
break;
case VIRTKEY_PREVIOUS_SLOT:
if (down) {
if (down && !Achievements::WarnUserIfChallengeModeActive()) {
SaveState::PrevSlot();
System_PostUIMessage("savestate_displayslot", "");
}
break;
case VIRTKEY_NEXT_SLOT:
if (down) {
if (down && !Achievements::WarnUserIfChallengeModeActive()) {
SaveState::NextSlot();
System_PostUIMessage("savestate_displayslot", "");
}
-1
View File
@@ -275,7 +275,6 @@ void RetroAchievementsSettingsScreen::CreateSettingsTab(UI::ViewGroup *viewGroup
viewGroup->Add(new CheckBox(&g_Config.bAchievementsChallengeMode, ac->T("Challenge Mode (no savestates)")));
viewGroup->Add(new CheckBox(&g_Config.bAchievementsEncoreMode, ac->T("Encore Mode")));
viewGroup->Add(new CheckBox(&g_Config.bAchievementsUnofficial, ac->T("Unofficial achievements")));
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);
+66 -39
View File
@@ -51,6 +51,7 @@
#include "Core/HLE/sceUmd.h"
#include "Core/SaveState.h"
#include "Core/Core.h"
#include "Core/RetroAchievements.h"
extern bool g_TakeScreenshot;
@@ -69,14 +70,23 @@ namespace MainWindow {
LRESULT CALLBACK AboutDlgProc(HWND, UINT, WPARAM, LPARAM);
void SetIngameMenuItemStates(HMENU menu, const GlobalUIState state) {
UINT menuEnable = state == UISTATE_INGAME || state == UISTATE_EXCEPTION ? MF_ENABLED : MF_GRAYED;
bool menuEnableBool = state == UISTATE_INGAME || state == UISTATE_EXCEPTION;
bool saveStateEnableBool = menuEnableBool;
if (Achievements::ChallengeModeActive()) {
saveStateEnableBool = false;
}
UINT menuEnable = menuEnableBool ? MF_ENABLED : MF_GRAYED;
UINT saveStateEnable = saveStateEnableBool ? MF_ENABLED : MF_GRAYED;
UINT menuInGameEnable = state == UISTATE_INGAME ? MF_ENABLED : MF_GRAYED;
UINT umdSwitchEnable = state == UISTATE_INGAME && getUMDReplacePermit() ? MF_ENABLED : MF_GRAYED;
EnableMenuItem(menu, ID_FILE_SAVESTATEFILE, menuEnable);
EnableMenuItem(menu, ID_FILE_LOADSTATEFILE, menuEnable);
EnableMenuItem(menu, ID_FILE_QUICKSAVESTATE, menuEnable);
EnableMenuItem(menu, ID_FILE_QUICKLOADSTATE, menuEnable);
EnableMenuItem(menu, ID_FILE_SAVESTATE_SLOT_MENU, saveStateEnable);
EnableMenuItem(menu, ID_FILE_SAVESTATEFILE, saveStateEnable);
EnableMenuItem(menu, ID_FILE_LOADSTATEFILE, saveStateEnable);
EnableMenuItem(menu, ID_FILE_QUICKSAVESTATE, saveStateEnable);
EnableMenuItem(menu, ID_FILE_QUICKLOADSTATE, saveStateEnable);
EnableMenuItem(menu, ID_EMULATION_PAUSE, menuEnable);
EnableMenuItem(menu, ID_EMULATION_STOP, menuEnable);
EnableMenuItem(menu, ID_EMULATION_RESET, menuEnable);
@@ -517,70 +527,87 @@ namespace MainWindow {
}
break;
case ID_FILE_LOADSTATEFILE:
if (W32Util::BrowseForFileName(true, hWnd, L"Load state", 0, L"Save States (*.ppst)\0*.ppst\0All files\0*.*\0\0", L"ppst", fn)) {
SetCursor(LoadCursor(0, IDC_WAIT));
SaveState::Load(Path(fn), -1, SaveStateActionFinished);
if (!Achievements::WarnUserIfChallengeModeActive()) {
if (W32Util::BrowseForFileName(true, hWnd, L"Load state", 0, L"Save States (*.ppst)\0*.ppst\0All files\0*.*\0\0", L"ppst", fn)) {
SetCursor(LoadCursor(0, IDC_WAIT));
SaveState::Load(Path(fn), -1, SaveStateActionFinished);
}
}
break;
case ID_FILE_SAVESTATEFILE:
if (W32Util::BrowseForFileName(false, hWnd, L"Save state", 0, L"Save States (*.ppst)\0*.ppst\0All files\0*.*\0\0", L"ppst", fn)) {
SetCursor(LoadCursor(0, IDC_WAIT));
SaveState::Save(Path(fn), -1, SaveStateActionFinished);
if (!Achievements::WarnUserIfChallengeModeActive()) {
if (W32Util::BrowseForFileName(false, hWnd, L"Save state", 0, L"Save States (*.ppst)\0*.ppst\0All files\0*.*\0\0", L"ppst", fn)) {
SetCursor(LoadCursor(0, IDC_WAIT));
SaveState::Save(Path(fn), -1, SaveStateActionFinished);
}
}
break;
case ID_FILE_SAVESTATE_NEXT_SLOT:
{
SaveState::NextSlot();
System_PostUIMessage("savestate_displayslot", "");
break;
}
case ID_FILE_SAVESTATE_NEXT_SLOT_HC:
{
if (!KeyMap::PspButtonHasMappings(VIRTKEY_NEXT_SLOT)) {
if (!Achievements::WarnUserIfChallengeModeActive()) {
SaveState::NextSlot();
System_PostUIMessage("savestate_displayslot", "");
}
break;
}
case ID_FILE_SAVESTATE_SLOT_1: g_Config.iCurrentStateSlot = 0; break;
case ID_FILE_SAVESTATE_SLOT_2: g_Config.iCurrentStateSlot = 1; break;
case ID_FILE_SAVESTATE_SLOT_3: g_Config.iCurrentStateSlot = 2; break;
case ID_FILE_SAVESTATE_SLOT_4: g_Config.iCurrentStateSlot = 3; break;
case ID_FILE_SAVESTATE_SLOT_5: g_Config.iCurrentStateSlot = 4; break;
case ID_FILE_QUICKLOADSTATE:
case ID_FILE_SAVESTATE_NEXT_SLOT_HC:
{
SetCursor(LoadCursor(0, IDC_WAIT));
SaveState::LoadSlot(PSP_CoreParameter().fileToStart, g_Config.iCurrentStateSlot, SaveStateActionFinished);
if (!Achievements::WarnUserIfChallengeModeActive()) {
if (!KeyMap::PspButtonHasMappings(VIRTKEY_NEXT_SLOT)) {
SaveState::NextSlot();
System_PostUIMessage("savestate_displayslot", "");
}
}
break;
}
case ID_FILE_QUICKLOADSTATE_HC:
{
if (!KeyMap::PspButtonHasMappings(VIRTKEY_LOAD_STATE))
{
case ID_FILE_SAVESTATE_SLOT_1:
case ID_FILE_SAVESTATE_SLOT_2:
case ID_FILE_SAVESTATE_SLOT_3:
case ID_FILE_SAVESTATE_SLOT_4:
case ID_FILE_SAVESTATE_SLOT_5:
if (!Achievements::WarnUserIfChallengeModeActive()) {
g_Config.iCurrentStateSlot = wmId - ID_FILE_SAVESTATE_SLOT_1;
}
break;
case ID_FILE_QUICKLOADSTATE:
if (!Achievements::WarnUserIfChallengeModeActive()) {
SetCursor(LoadCursor(0, IDC_WAIT));
SaveState::LoadSlot(PSP_CoreParameter().fileToStart, g_Config.iCurrentStateSlot, SaveStateActionFinished);
}
break;
case ID_FILE_QUICKLOADSTATE_HC:
{
if (!Achievements::WarnUserIfChallengeModeActive()) {
if (!KeyMap::PspButtonHasMappings(VIRTKEY_LOAD_STATE)) {
SetCursor(LoadCursor(0, IDC_WAIT));
SaveState::LoadSlot(PSP_CoreParameter().fileToStart, g_Config.iCurrentStateSlot, SaveStateActionFinished);
}
}
break;
}
case ID_FILE_QUICKSAVESTATE:
{
SetCursor(LoadCursor(0, IDC_WAIT));
SaveState::SaveSlot(PSP_CoreParameter().fileToStart, g_Config.iCurrentStateSlot, SaveStateActionFinished);
if (!Achievements::WarnUserIfChallengeModeActive()) {
SetCursor(LoadCursor(0, IDC_WAIT));
SaveState::SaveSlot(PSP_CoreParameter().fileToStart, g_Config.iCurrentStateSlot, SaveStateActionFinished);
}
break;
}
case ID_FILE_QUICKSAVESTATE_HC:
{
if (!KeyMap::PspButtonHasMappings(VIRTKEY_SAVE_STATE))
{
SetCursor(LoadCursor(0, IDC_WAIT));
SaveState::SaveSlot(PSP_CoreParameter().fileToStart, g_Config.iCurrentStateSlot, SaveStateActionFinished);
break;
if (!Achievements::WarnUserIfChallengeModeActive()) {
if (!KeyMap::PspButtonHasMappings(VIRTKEY_SAVE_STATE))
{
SetCursor(LoadCursor(0, IDC_WAIT));
SaveState::SaveSlot(PSP_CoreParameter().fileToStart, g_Config.iCurrentStateSlot, SaveStateActionFinished);
break;
}
}
break;
}
+4 -1
View File
@@ -24,6 +24,9 @@
[Achievements]
%d achievements, %d points = %d achievements, %d points
%1: Leaderboard attempt started = %1: Leaderboard attempt started
%1: Leaderboard attempt failed = %1: Leaderboard attempt failed
%1: Submitting leaderboard score: %2! = %1: Submitting leaderboard score: %2!
Account = Account
Achievements = Achievements
Achievements are disabled = Achievements are disabled
@@ -38,7 +41,7 @@ Links = Links
Locked achievements = Locked achievements
Log bad memory accesses = Log bad memory accesses
Mastered %1 = Mastered %1
Not available in Challenge Mode = Not available in Challenge Mode
This feature is not available in Challenge Mode = This feature is not available in Challenge Mode
Save states not available in Challenge Mode = Save states not available in Challenge Mode
Register on www.retroachievements.org = Register on www.retroachievements.org
RetroAchievements are not available for this game = RetroAchievements are not available for this game