System: Share memory cards in multi-disc games
Even without playlists.
This commit is contained in:
parent
7d914a9384
commit
c7f987bfb7
|
@ -3583,8 +3583,8 @@ void FullscreenUI::DrawMemoryCardSettingsPage()
|
|||
SetSettingsChanged(bsi);
|
||||
}
|
||||
|
||||
DrawToggleSetting(bsi, FSUI_ICONSTR(ICON_FA_SEARCH, "Use Single Card For Sub-Images"),
|
||||
FSUI_CSTR("When using a multi-disc image (m3u/pbp) and per-game (title) memory cards, "
|
||||
DrawToggleSetting(bsi, FSUI_ICONSTR(ICON_FA_SEARCH, "Use Single Card For Multi-Disc Games"),
|
||||
FSUI_CSTR("When playing a multi-disc game and using per-game (title) memory cards, "
|
||||
"use a single memory card for all discs."),
|
||||
"MemoryCards", "UsePlaylistTitle", true);
|
||||
|
||||
|
|
|
@ -192,17 +192,14 @@ bool Pad::DoStateController(StateWrapper& sw, u32 i)
|
|||
if (g_settings.load_devices_from_save_states)
|
||||
{
|
||||
Host::AddFormattedOSDMessage(
|
||||
10.0f,
|
||||
TRANSLATE("OSDMessage",
|
||||
"Save state contains controller type %s in port %u, but %s is used. Switching."),
|
||||
10.0f, TRANSLATE("OSDMessage", "Save state contains controller type %s in port %u, but %s is used. Switching."),
|
||||
Settings::GetControllerTypeName(state_controller_type), i + 1u,
|
||||
Settings::GetControllerTypeName(controller_type));
|
||||
}
|
||||
else
|
||||
{
|
||||
Host::AddFormattedOSDMessage(
|
||||
10.0f, TRANSLATE("OSDMessage", "Ignoring mismatched controller type %s in port %u."),
|
||||
Settings::GetControllerTypeName(state_controller_type), i + 1u);
|
||||
Host::AddFormattedOSDMessage(10.0f, TRANSLATE("OSDMessage", "Ignoring mismatched controller type %s in port %u."),
|
||||
Settings::GetControllerTypeName(state_controller_type), i + 1u);
|
||||
}
|
||||
|
||||
// dev-friendly untranslated console log.
|
||||
|
@ -256,8 +253,7 @@ bool Pad::DoStateMemcard(StateWrapper& sw, u32 i, bool is_memory_state)
|
|||
{
|
||||
Host::AddFormattedOSDMessage(
|
||||
20.0f,
|
||||
TRANSLATE("OSDMessage",
|
||||
"Memory card %u present in save state but not in system. Creating temporary card."),
|
||||
TRANSLATE("OSDMessage", "Memory card %u present in save state but not in system. Creating temporary card."),
|
||||
i + 1u);
|
||||
s_memory_cards[i] = MemoryCard::Create();
|
||||
}
|
||||
|
@ -296,7 +292,7 @@ bool Pad::DoStateMemcard(StateWrapper& sw, u32 i, bool is_memory_state)
|
|||
Host::AddFormattedOSDMessage(
|
||||
20.0f,
|
||||
TRANSLATE("OSDMessage",
|
||||
"Memory card %u from save state does match current card data. Simulating replugging."),
|
||||
"Memory card %u from save state does match current card data. Simulating replugging."),
|
||||
i + 1u);
|
||||
|
||||
// this is a potentially serious issue - some games cache info from memcards and jumping around
|
||||
|
@ -312,8 +308,7 @@ bool Pad::DoStateMemcard(StateWrapper& sw, u32 i, bool is_memory_state)
|
|||
else
|
||||
{
|
||||
Host::AddFormattedOSDMessage(
|
||||
20.0f,
|
||||
TRANSLATE("OSDMessage", "Memory card %u present in save state but not in system. Ignoring card."),
|
||||
20.0f, TRANSLATE("OSDMessage", "Memory card %u present in save state but not in system. Ignoring card."),
|
||||
i + 1u);
|
||||
}
|
||||
|
||||
|
@ -325,16 +320,14 @@ 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."),
|
||||
20.0f, TRANSLATE("OSDMessage", "Memory card %u present in system but not in save state. Removing card."),
|
||||
i + 1u);
|
||||
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."),
|
||||
20.0f, TRANSLATE("OSDMessage", "Memory card %u present in system but not in save state. Replugging card."),
|
||||
i + 1u);
|
||||
s_memory_cards[i]->Reset();
|
||||
}
|
||||
|
@ -545,6 +538,10 @@ MemoryCard* Pad::GetMemoryCard(u32 slot)
|
|||
|
||||
void Pad::SetMemoryCard(u32 slot, std::unique_ptr<MemoryCard> dev)
|
||||
{
|
||||
Log_InfoPrintf("Memory card slot %u: %s", slot,
|
||||
dev ? (dev->GetFilename().empty() ? "<no file configured>" : dev->GetFilename().c_str()) :
|
||||
"<unplugged>");
|
||||
|
||||
s_memory_cards[slot] = std::move(dev);
|
||||
}
|
||||
|
||||
|
@ -798,7 +795,8 @@ void Pad::DoTransfer(TickCount ticks_late)
|
|||
const u32 frame_number = System::GetFrameNumber();
|
||||
|
||||
// consider u32 overflow case
|
||||
if (ShouldAvoidSavingToState() && (frame_number - s_last_memory_card_transfer_frame) > GetMaximumRollbackFrames())
|
||||
if (ShouldAvoidSavingToState() &&
|
||||
(frame_number - s_last_memory_card_transfer_frame) > GetMaximumRollbackFrames())
|
||||
BackupMemoryCardState();
|
||||
|
||||
s_last_memory_card_transfer_frame = frame_number;
|
||||
|
|
|
@ -1271,7 +1271,7 @@ std::string Settings::GetSharedMemoryCardPath(u32 slot) const
|
|||
return ret;
|
||||
}
|
||||
|
||||
std::string Settings::GetGameMemoryCardPath(const char* serial, u32 slot)
|
||||
std::string Settings::GetGameMemoryCardPath(const std::string_view& serial, u32 slot)
|
||||
{
|
||||
return Path::Combine(EmuFolders::MemoryCards, fmt::format("{}_{}.mcd", serial, slot + 1));
|
||||
}
|
||||
|
|
|
@ -312,7 +312,7 @@ struct Settings
|
|||
std::string GetSharedMemoryCardPath(u32 slot) const;
|
||||
|
||||
/// Returns the default path to a memory card for a specific game.
|
||||
static std::string GetGameMemoryCardPath(const char* serial, u32 slot);
|
||||
static std::string GetGameMemoryCardPath(const std::string_view& serial, u32 slot);
|
||||
|
||||
static void CPUOverclockPercentToFraction(u32 percent, u32* numerator, u32* denominator);
|
||||
static u32 CPUOverclockFractionToPercent(u32 numerator, u32 denominator);
|
||||
|
|
|
@ -2304,8 +2304,8 @@ bool System::InternalSaveState(ByteStream* state, u32 screenshot_size /* = 256 *
|
|||
u32 screenshot_stride;
|
||||
GPUTexture::Format screenshot_format;
|
||||
if (g_gpu_device->RenderScreenshot(screenshot_width, screenshot_height,
|
||||
Common::Rectangle<s32>::FromExtents(0, 0, screenshot_width, screenshot_height),
|
||||
&screenshot_buffer, &screenshot_stride, &screenshot_format) &&
|
||||
Common::Rectangle<s32>::FromExtents(0, 0, screenshot_width, screenshot_height),
|
||||
&screenshot_buffer, &screenshot_stride, &screenshot_format) &&
|
||||
GPUTexture::ConvertTextureDataToRGBA8(screenshot_width, screenshot_height, screenshot_buffer, screenshot_stride,
|
||||
screenshot_format))
|
||||
{
|
||||
|
@ -2893,8 +2893,43 @@ std::unique_ptr<MemoryCard> System::GetMemoryCardForSlot(u32 slot, MemoryCardTyp
|
|||
}
|
||||
else
|
||||
{
|
||||
return MemoryCard::Open(g_settings.GetGameMemoryCardPath(
|
||||
MemoryCard::SanitizeGameTitleForFileName(s_running_game_title).c_str(), slot));
|
||||
std::string card_path;
|
||||
|
||||
// Playlist - use title if different.
|
||||
if (HasMediaSubImages() && s_running_game_entry && s_running_game_title != s_running_game_entry->title)
|
||||
{
|
||||
card_path = g_settings.GetGameMemoryCardPath(
|
||||
MemoryCard::SanitizeGameTitleForFileName(s_running_game_entry->title), slot);
|
||||
}
|
||||
// Multi-disc game - use disc set name.
|
||||
else if (s_running_game_entry && !s_running_game_entry->disc_set_name.empty())
|
||||
{
|
||||
card_path = g_settings.GetGameMemoryCardPath(
|
||||
MemoryCard::SanitizeGameTitleForFileName(s_running_game_entry->disc_set_name), slot);
|
||||
}
|
||||
|
||||
// But prefer a disc-specific card if one already exists.
|
||||
std::string disc_card_path =
|
||||
g_settings.GetGameMemoryCardPath(MemoryCard::SanitizeGameTitleForFileName(s_running_game_entry->title), slot);
|
||||
if (disc_card_path != card_path)
|
||||
{
|
||||
if (card_path.empty() || !g_settings.memory_card_use_playlist_title ||
|
||||
FileSystem::FileExists(disc_card_path.c_str()))
|
||||
{
|
||||
if (g_settings.memory_card_use_playlist_title && !card_path.empty())
|
||||
{
|
||||
Host::AddIconOSDMessage(
|
||||
fmt::format("DiscSpecificMC{}", slot), ICON_FA_SD_CARD,
|
||||
fmt::format(TRANSLATE_FS("System", "Using disc-specific memory card '{}' instead of per-game card."),
|
||||
Path::GetFileName(disc_card_path)),
|
||||
Host::OSD_INFO_DURATION);
|
||||
}
|
||||
|
||||
card_path = std::move(disc_card_path);
|
||||
}
|
||||
}
|
||||
|
||||
return MemoryCard::Open(card_path.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3145,9 +3180,9 @@ void System::UpdateRunningGame(const char* path, CDImage* image, bool booting)
|
|||
s_running_game_title = Path::GetFileTitle(FileSystem::GetDisplayNameFromPath(path));
|
||||
}
|
||||
|
||||
if (image->HasSubImages() && g_settings.memory_card_use_playlist_title)
|
||||
if (image->HasSubImages())
|
||||
{
|
||||
std::string image_title(image->GetMetadata("title"));
|
||||
std::string image_title = image->GetMetadata("title");
|
||||
if (!image_title.empty())
|
||||
s_running_game_title = std::move(image_title);
|
||||
}
|
||||
|
@ -3456,8 +3491,7 @@ void System::CheckForSettingsChanges(const Settings& old_settings)
|
|||
|
||||
if (g_settings.memory_card_types != old_settings.memory_card_types ||
|
||||
g_settings.memory_card_paths != old_settings.memory_card_paths ||
|
||||
(g_settings.memory_card_use_playlist_title != old_settings.memory_card_use_playlist_title &&
|
||||
HasMediaSubImages()))
|
||||
(g_settings.memory_card_use_playlist_title != old_settings.memory_card_use_playlist_title))
|
||||
{
|
||||
UpdateMemoryCardTypes();
|
||||
}
|
||||
|
@ -4448,7 +4482,7 @@ void System::UpdateSoftwareCursor()
|
|||
if (image && image->IsValid())
|
||||
{
|
||||
g_gpu_device->SetSoftwareCursor(image->GetPixels(), image->GetWidth(), image->GetHeight(), image->GetPitch(),
|
||||
image_scale);
|
||||
image_scale);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
@ -58,13 +58,13 @@ void MemoryCardSettingsWidget::createUi(SettingsDialog* dialog)
|
|||
box_layout->addLayout(hbox);
|
||||
}
|
||||
|
||||
QCheckBox* playlist_title_as_game_title = new QCheckBox(tr("Use Single Card For Sub-Images"), box);
|
||||
QCheckBox* playlist_title_as_game_title = new QCheckBox(tr("Use Single Card For Multi-Disc Games"), box);
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(m_dialog->getSettingsInterface(), playlist_title_as_game_title,
|
||||
"MemoryCards", "UsePlaylistTitle", true);
|
||||
box_layout->addWidget(playlist_title_as_game_title);
|
||||
dialog->registerWidgetHelp(
|
||||
playlist_title_as_game_title, tr("Use Single Card For Sub-Images"), tr("Checked"),
|
||||
tr("When using a multi-disc format (m3u/pbp) and per-game (title) memory cards, a single memory card "
|
||||
playlist_title_as_game_title, tr("Use Single Card For Multi-Disc Games"), tr("Checked"),
|
||||
tr("When playing a multi-disc game and using per-game (title) memory cards, a single memory card "
|
||||
"will be used for all discs. If unchecked, a separate card will be used for each disc."));
|
||||
|
||||
box_layout->addWidget(QtUtils::CreateHorizontalLine(box));
|
||||
|
|
Loading…
Reference in New Issue