-
Notifications
You must be signed in to change notification settings - Fork 726
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Pad: Fix unconditional memory card replug on load state
- Loading branch information
Showing
3 changed files
with
52 additions
and
27 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,4 @@ | ||
// SPDX-FileCopyrightText: 2019-2023 Connor McLaughlin <[email protected]> | ||
// SPDX-FileCopyrightText: 2019-2024 Connor McLaughlin <[email protected]> | ||
// SPDX-License-Identifier: (GPL-3.0 OR CC-BY-NC-ND-4.0) | ||
|
||
#include "memory_card.h" | ||
|
@@ -65,6 +65,19 @@ bool MemoryCard::DoState(StateWrapper& sw) | |
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() | ||
{ | ||
m_state = State::Idle; | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,4 @@ | ||
// SPDX-FileCopyrightText: 2019-2023 Connor McLaughlin <[email protected]> and contributors. | ||
// SPDX-FileCopyrightText: 2019-2024 Connor McLaughlin <[email protected]> and contributors. | ||
// SPDX-License-Identifier: (GPL-3.0 OR CC-BY-NC-ND-4.0) | ||
|
||
#include "pad.h" | ||
|
@@ -19,6 +19,8 @@ | |
#include "common/fifo_queue.h" | ||
#include "common/log.h" | ||
|
||
#include "IconsFontAwesome5.h" | ||
|
||
#include <array> | ||
#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) | ||
{ | ||
Host::AddFormattedOSDMessage( | ||
20.0f, | ||
TRANSLATE("OSDMessage", "Memory card %u present in save state but not in system. Creating temporary card."), | ||
i + 1u); | ||
Host::AddIconOSDMessage( | ||
fmt::format("card_load_warning_{}", i), ICON_FA_SD_CARD, | ||
fmt::format( | ||
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(); | ||
} | ||
|
||
MemoryCard* card_ptr = s_memory_cards[i].get(); | ||
std::unique_ptr<MemoryCard> card_from_state; | ||
|
||
if (card_present_in_state) | ||
{ | ||
if (sw.IsReading() && !g_settings.load_devices_from_save_states) | ||
|
@@ -284,38 +286,42 @@ bool Pad::DoStateMemcard(StateWrapper& sw, u32 i, bool is_memory_state) | |
if (sw.IsWriting()) | ||
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]->GetData() == card_from_state->GetData()) | ||
if (s_memory_cards[i]->GetData() == card_ptr->GetData()) | ||
{ | ||
card_from_state->SetFilename(s_memory_cards[i]->GetFilename()); | ||
s_memory_cards[i] = std::move(card_from_state); | ||
Log_DevFmt("Card {} data matches, copying state", i + 1u); | ||
s_memory_cards[i]->CopyState(card_ptr); | ||
} | ||
else | ||
{ | ||
Host::AddFormattedOSDMessage( | ||
20.0f, | ||
TRANSLATE("OSDMessage", | ||
"Memory card %u from save state does match current card data. Simulating replugging."), | ||
i + 1u); | ||
Host::AddIconOSDMessage( | ||
fmt::format("card_load_warning_{}", i), ICON_FA_SD_CARD, | ||
fmt::format( | ||
TRANSLATE_FS("OSDMessage", | ||
"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 | ||
// with savestates can lead to card corruption on the next save attempts (and may not be obvious | ||
// until much later). One workaround is to forcibly eject the card for 30+ frames, long enough | ||
// 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. | ||
|
||
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(); | ||
} | ||
} | ||
else | ||
{ | ||
Host::AddFormattedOSDMessage( | ||
20.0f, TRANSLATE("OSDMessage", "Memory card %u present in save state but not in system. Ignoring card."), | ||
i + 1u); | ||
Host::AddIconOSDMessage( | ||
fmt::format("card_load_warning_{}", i), ICON_FA_SD_CARD, | ||
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; | ||
|
@@ -325,16 +331,21 @@ bool Pad::DoStateMemcard(StateWrapper& sw, u32 i, bool is_memory_state) | |
{ | ||
if (g_settings.load_devices_from_save_states) | ||
{ | ||
Host::AddFormattedOSDMessage( | ||
20.0f, TRANSLATE("OSDMessage", "Memory card %u present in system but not in save state. Removing card."), | ||
i + 1u); | ||
Host::AddIconOSDMessage( | ||
fmt::format("card_load_warning_{}", i), ICON_FA_SD_CARD, | ||
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(); | ||
} | ||
else | ||
{ | ||
Host::AddFormattedOSDMessage( | ||
20.0f, TRANSLATE("OSDMessage", "Memory card %u present in system but not in save state. Replugging card."), | ||
i + 1u); | ||
Host::AddIconOSDMessage( | ||
fmt::format("card_load_warning_{}", i), ICON_FA_SD_CARD, | ||
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(); | ||
} | ||
} | ||
|