Pad: Fix unconditional memory card replug on load state

This commit is contained in:
Stenzek 2024-03-29 12:34:42 +10:00
parent e54ad1956a
commit c41563c7dc
No known key found for this signature in database
3 changed files with 52 additions and 27 deletions

View file

@ -1,4 +1,4 @@
// SPDX-FileCopyrightText: 2019-2023 Connor McLaughlin <stenzek@gmail.com> // SPDX-FileCopyrightText: 2019-2024 Connor McLaughlin <stenzek@gmail.com>
// SPDX-License-Identifier: (GPL-3.0 OR CC-BY-NC-ND-4.0) // SPDX-License-Identifier: (GPL-3.0 OR CC-BY-NC-ND-4.0)
#include "memory_card.h" #include "memory_card.h"
@ -65,6 +65,19 @@ bool MemoryCard::DoState(StateWrapper& sw)
return !sw.HasError(); return !sw.HasError();
} }
void MemoryCard::CopyState(const MemoryCard* src)
{
DebugAssert(m_data == src->m_data);
m_state = src->m_state;
m_FLAG.bits = src->m_FLAG.bits;
m_address = src->m_address;
m_sector_offset = src->m_sector_offset;
m_checksum = src->m_checksum;
m_last_byte = src->m_last_byte;
m_changed = src->m_changed;
}
void MemoryCard::ResetTransferState() void MemoryCard::ResetTransferState()
{ {
m_state = State::Idle; m_state = State::Idle;

View file

@ -30,6 +30,7 @@ public:
void Reset(); void Reset();
bool DoState(StateWrapper& sw); bool DoState(StateWrapper& sw);
void CopyState(const MemoryCard* src);
void ResetTransferState(); void ResetTransferState();
bool Transfer(const u8 data_in, u8* data_out); bool Transfer(const u8 data_in, u8* data_out);

View file

@ -1,4 +1,4 @@
// SPDX-FileCopyrightText: 2019-2023 Connor McLaughlin <stenzek@gmail.com> and contributors. // SPDX-FileCopyrightText: 2019-2024 Connor McLaughlin <stenzek@gmail.com> and contributors.
// SPDX-License-Identifier: (GPL-3.0 OR CC-BY-NC-ND-4.0) // SPDX-License-Identifier: (GPL-3.0 OR CC-BY-NC-ND-4.0)
#include "pad.h" #include "pad.h"
@ -19,6 +19,8 @@
#include "common/fifo_queue.h" #include "common/fifo_queue.h"
#include "common/log.h" #include "common/log.h"
#include "IconsFontAwesome5.h"
#include <array> #include <array>
#include <memory> #include <memory>
@ -257,16 +259,16 @@ bool Pad::DoStateMemcard(StateWrapper& sw, u32 i, bool is_memory_state)
if (card_present_in_state && !s_memory_cards[i] && g_settings.load_devices_from_save_states) if (card_present_in_state && !s_memory_cards[i] && g_settings.load_devices_from_save_states)
{ {
Host::AddFormattedOSDMessage( Host::AddIconOSDMessage(
20.0f, fmt::format("card_load_warning_{}", i), ICON_FA_SD_CARD,
TRANSLATE("OSDMessage", "Memory card %u present in save state but not in system. Creating temporary card."), fmt::format(
i + 1u); TRANSLATE_FS("OSDMessage", "Memory card {} present in save state but not in system. Creating temporary card."),
i + 1u),
Host::OSD_ERROR_DURATION);
s_memory_cards[i] = MemoryCard::Create(); s_memory_cards[i] = MemoryCard::Create();
} }
MemoryCard* card_ptr = s_memory_cards[i].get(); MemoryCard* card_ptr = s_memory_cards[i].get();
std::unique_ptr<MemoryCard> card_from_state;
if (card_present_in_state) if (card_present_in_state)
{ {
if (sw.IsReading() && !g_settings.load_devices_from_save_states) if (sw.IsReading() && !g_settings.load_devices_from_save_states)
@ -284,22 +286,24 @@ bool Pad::DoStateMemcard(StateWrapper& sw, u32 i, bool is_memory_state)
if (sw.IsWriting()) if (sw.IsWriting())
return true; // all done as far as writes concerned. return true; // all done as far as writes concerned.
if (card_from_state) if (card_ptr != s_memory_cards[i].get())
{ {
if (s_memory_cards[i]) if (s_memory_cards[i])
{ {
if (s_memory_cards[i]->GetData() == card_from_state->GetData()) if (s_memory_cards[i]->GetData() == card_ptr->GetData())
{ {
card_from_state->SetFilename(s_memory_cards[i]->GetFilename()); Log_DevFmt("Card {} data matches, copying state", i + 1u);
s_memory_cards[i] = std::move(card_from_state); s_memory_cards[i]->CopyState(card_ptr);
} }
else else
{ {
Host::AddFormattedOSDMessage( Host::AddIconOSDMessage(
20.0f, fmt::format("card_load_warning_{}", i), ICON_FA_SD_CARD,
TRANSLATE("OSDMessage", fmt::format(
"Memory card %u from save state does match current card data. Simulating replugging."), TRANSLATE_FS("OSDMessage",
i + 1u); "Memory card {} from save state does match current card data. Simulating replugging."),
i + 1u),
Host::OSD_WARNING_DURATION);
// this is a potentially serious issue - some games cache info from memcards and jumping around // this is a potentially serious issue - some games cache info from memcards and jumping around
// with savestates can lead to card corruption on the next save attempts (and may not be obvious // with savestates can lead to card corruption on the next save attempts (and may not be obvious
@ -307,15 +311,17 @@ bool Pad::DoStateMemcard(StateWrapper& sw, u32 i, bool is_memory_state)
// for the game to decide it was removed and purge its cache. Once implemented, this could be // for the game to decide it was removed and purge its cache. Once implemented, this could be
// described as deferred re-plugging in the log. // described as deferred re-plugging in the log.
Log_WarningPrintf("Memory card %u data mismatch. Using current data via instant-replugging.", i + 1u); Log_WarningFmt("Memory card {} data mismatch. Using current data via instant-replugging.", i + 1u);
s_memory_cards[i]->Reset(); s_memory_cards[i]->Reset();
} }
} }
else else
{ {
Host::AddFormattedOSDMessage( Host::AddIconOSDMessage(
20.0f, TRANSLATE("OSDMessage", "Memory card %u present in save state but not in system. Ignoring card."), fmt::format("card_load_warning_{}", i), ICON_FA_SD_CARD,
i + 1u); fmt::format(
TRANSLATE_FS("OSDMessage", "Memory card {} present in save state but not in system. Ignoring card."), i + 1u),
Host::OSD_ERROR_DURATION);
} }
return true; return true;
@ -325,16 +331,21 @@ bool Pad::DoStateMemcard(StateWrapper& sw, u32 i, bool is_memory_state)
{ {
if (g_settings.load_devices_from_save_states) if (g_settings.load_devices_from_save_states)
{ {
Host::AddFormattedOSDMessage( Host::AddIconOSDMessage(
20.0f, TRANSLATE("OSDMessage", "Memory card %u present in system but not in save state. Removing card."), fmt::format("card_load_warning_{}", i), ICON_FA_SD_CARD,
i + 1u); fmt::format(
TRANSLATE_FS("OSDMessage", "Memory card {} present in system but not in save state. Removing card."), i + 1u),
Host::OSD_ERROR_DURATION);
s_memory_cards[i].reset(); s_memory_cards[i].reset();
} }
else else
{ {
Host::AddFormattedOSDMessage( Host::AddIconOSDMessage(
20.0f, TRANSLATE("OSDMessage", "Memory card %u present in system but not in save state. Replugging card."), fmt::format("card_load_warning_{}", i), ICON_FA_SD_CARD,
i + 1u); fmt::format(
TRANSLATE_FS("OSDMessage", "Memory card {} present in system but not in save state. Replugging card."),
i + 1u),
Host::OSD_WARNING_DURATION);
s_memory_cards[i]->Reset(); s_memory_cards[i]->Reset();
} }
} }