Skip to content

Commit

Permalink
SIO/MCD: hugely improved memcard swapping + reinsertion
Browse files Browse the repository at this point in the history
  • Loading branch information
refractionpcsx2 committed Jun 23, 2023
1 parent c77d8b3 commit 651d5e7
Show file tree
Hide file tree
Showing 8 changed files with 204 additions and 189 deletions.
253 changes: 124 additions & 129 deletions pcsx2-qt/Translations/pcsx2-qt_en.ts

Large diffs are not rendered by default.

2 changes: 2 additions & 0 deletions pcsx2/CDVD/CDVD.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
#include "IopHw.h"
#include "IopDma.h"
#include "VMManager.h"
#include "Sio.h"

#include <cctype>
#include <ctime>
Expand Down Expand Up @@ -1528,6 +1529,7 @@ void cdvdVsync()
cdvd.RTCcount = 0;

cdvdUpdateTrayState();
AutoEject::CountDownTicks();

cdvd.RTC.second++;
if (cdvd.RTC.second < 60)
Expand Down
37 changes: 27 additions & 10 deletions pcsx2/MemoryCardFile.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@

#include "MemoryCardFile.h"
#include "MemoryCardFolder.h"
#include "Sio.h"

#include "System.h"
#include "Config.h"
Expand Down Expand Up @@ -292,14 +293,11 @@ void FileMemoryCard::Open()
cont = true;
}

if (EmuConfig.Mcd[slot].Type != MemoryCardType::File)
{
str = "[is not memcard file]";
if (EmuConfig.Mcd[slot].Type == MemoryCardType::File)
Console.WriteLn(cont ? Color_Gray : Color_Green, fmt::format("McdSlot {} [File]: {}", slot, str));
else
cont = true;
}

Console.WriteLn(cont ? Color_Gray : Color_Green, "McdSlot %u [File]: %.*s", slot,
static_cast<int>(str.size()), str.data());
if (cont)
continue;

Expand Down Expand Up @@ -660,6 +658,20 @@ void FileMcd_EmuClose()
Mcd::impl.Close();
}

void FileMcd_CancelEject()
{
AutoEject::ClearAll();
}

void FileMcd_Reopen(std::string new_serial)
{
Console.WriteLn("Reopening memory cards...");
FileMcd_EmuClose();
FileMcd_EmuOpen();

sioSetGameSerial(new_serial);
}

s32 FileMcd_IsPresent(uint port, uint slot)
{
const uint combinedSlot = FileMcd_ConvertToSlot(port, slot);
Expand Down Expand Up @@ -776,20 +788,25 @@ void FileMcd_NextFrame(uint port, uint slot)
}
}

bool FileMcd_ReIndex(uint port, uint slot, const std::string& filter)
int FileMcd_ReIndex(uint port, uint slot, const std::string& filter)
{
const uint combinedSlot = FileMcd_ConvertToSlot(port, slot);
const int combinedSlot = FileMcd_ConvertToSlot(port, slot);

switch (EmuConfig.Mcd[combinedSlot].Type)
{
//case MemoryCardType::File:
// return Mcd::impl.ReIndex( combinedSlot, filter );
// break;
case MemoryCardType::Folder:
return Mcd::implFolder.ReIndex(combinedSlot, EmuConfig.McdFolderAutoManage, filter);
if (!Mcd::implFolder.ReIndex(combinedSlot, EmuConfig.McdFolderAutoManage, filter))
return -1;
break;
default:
return false;
return -1;
break;
}

return combinedSlot;
}

// --------------------------------------------------------------------------------------
Expand Down
4 changes: 3 additions & 1 deletion pcsx2/MemoryCardFile.h
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,8 @@ extern std::string FileMcd_GetDefaultName(uint slot);
uint FileMcd_ConvertToSlot(uint port, uint slot);
void FileMcd_EmuOpen();
void FileMcd_EmuClose();
void FileMcd_CancelEject();
void FileMcd_Reopen(std::string new_serial);
s32 FileMcd_IsPresent(uint port, uint slot);
void FileMcd_GetSizeInfo(uint port, uint slot, McdSizeInfo* outways);
bool FileMcd_IsPSX(uint port, uint slot);
Expand All @@ -55,7 +57,7 @@ s32 FileMcd_Save(uint port, uint slot, const u8* src, u32 adr, int size);
s32 FileMcd_EraseBlock(uint port, uint slot, u32 adr);
u64 FileMcd_GetCRC(uint port, uint slot);
void FileMcd_NextFrame(uint port, uint slot);
bool FileMcd_ReIndex(uint port, uint slot, const std::string& filter);
int FileMcd_ReIndex(uint port, uint slot, const std::string& filter);

std::vector<AvailableMcdInfo> FileMcd_GetAvailableCards(bool include_in_use_cards);
std::optional<AvailableMcdInfo> FileMcd_GetCardInfo(const std::string_view& name);
Expand Down
1 change: 0 additions & 1 deletion pcsx2/Pcsx2Config.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1373,7 +1373,6 @@ Pcsx2Config::Pcsx2Config()
{
Mcd[slot].Enabled = !FileMcd_IsMultitapSlot(slot); // enables main 2 slots
Mcd[slot].Filename = FileMcd_GetDefaultName(slot);

// Folder memory card is autodetected later.
Mcd[slot].Type = MemoryCardType::File;
}
Expand Down
50 changes: 27 additions & 23 deletions pcsx2/Sio.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -204,15 +204,6 @@ void Sio0::SetTxData(u8 value)
if (mcd->autoEjectTicks)
{
SetRxData(0x00);
mcd->autoEjectTicks--;

if (mcd->autoEjectTicks == 0)
{
Host::AddKeyedOSDMessage(fmt::format("AutoEjectSlotClear{}{}", port, slot),
fmt::format(TRANSLATE_SV("MemoryCard", "Memory Card in port %d / slot %d reinserted"),
port + 1, slot + 1),
Host::OSD_INFO_DURATION);
}

return;
}
Expand Down Expand Up @@ -585,16 +576,6 @@ void Sio2::Memcard()
fifoOut.push_back(0x00);
}

mcd->autoEjectTicks--;

if (mcd->autoEjectTicks == 0)
{
Host::AddKeyedOSDMessage(fmt::format("AutoEjectSlotClear{}{}", port, slot),
fmt::format(
TRANSLATE_SV("MemoryCard", "Memory Card in port {} / slot {} reinserted."), port + 1, slot + 1),
Host::OSD_INFO_DURATION);
}

return;
}

Expand Down Expand Up @@ -833,7 +814,8 @@ void sioNextFrame() {
void sioSetGameSerial( const std::string& serial ) {
for ( uint port = 0; port < 2; ++port ) {
for ( uint slot = 0; slot < 4; ++slot ) {
if ( mcds[port][slot].ReIndex( serial ) ) {
if ( int index = mcds[port][slot].ReIndex( serial ) >= 0 ) {
Console.WriteLn("Ejecting Memory Card %u (port %u slot %u) due to source change. Reinsert in 1 second.", index, port, slot);
AutoEject::Set( port, slot );
}
}
Expand Down Expand Up @@ -915,11 +897,33 @@ bool sioPortAndSlotIsMultitap(u32 port, u32 slot)
return (slot != 0);
}

void AutoEject::CountDownTicks()
{
bool reinserted = false;
for (size_t port = 0; port < SIO::PORTS; port++)
{
for (size_t slot = 0; slot < SIO::SLOTS; slot++)
{
if (mcds[port][slot].autoEjectTicks > 0)
{
if (--mcds[port][slot].autoEjectTicks == 0)
{
Host::AddKeyedOSDMessage(fmt::format("AutoEjectSlotClear{}{}", port, slot),
fmt::format(TRANSLATE_SV("MemoryCard", "Memory card in port {} / slot {} reinserted"),
port + 1, slot + 1),
Host::OSD_INFO_DURATION);
}
}
}
}
}

void AutoEject::Set(size_t port, size_t slot)
{
if (EmuConfig.McdEnableEjection)
if (EmuConfig.McdEnableEjection && mcds[port][slot].autoEjectTicks == 0)
{
mcds[port][slot].autoEjectTicks = 60;
mcds[port][slot].autoEjectTicks = 1; // 1 second is enough.
mcds[port][slot].term = 0x55; // Reset terminator to default (0x55), forces the PS2 to recheck the memcard.
}
}

Expand All @@ -931,7 +935,7 @@ void AutoEject::Clear(size_t port, size_t slot)
void AutoEject::SetAll()
{
Host::AddIconOSDMessage("AutoEjectAllSet", ICON_FA_SD_CARD,
TRANSLATE_SV("MemoryCard", "Force ejecting all Memory Cards."), Host::OSD_INFO_DURATION);
TRANSLATE_SV("MemoryCard", "Force ejecting all Memory Cards. Reinserting in 1 second."), Host::OSD_INFO_DURATION);

for (size_t port = 0; port < SIO::PORTS; port++)
{
Expand Down
3 changes: 2 additions & 1 deletion pcsx2/Sio.h
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ struct _mcd
FileMcd_NextFrame( port, slot );
}

bool ReIndex(const std::string& filter) {
int ReIndex(const std::string& filter) {
return FileMcd_ReIndex(port, slot, filter);
}
};
Expand Down Expand Up @@ -243,6 +243,7 @@ extern void sioSetGameSerial(const std::string& serial);

namespace AutoEject
{
extern void CountDownTicks();
extern void Set(size_t port, size_t slot);
extern void Clear(size_t port, size_t slot);
extern void SetAll();
Expand Down
43 changes: 19 additions & 24 deletions pcsx2/VMManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -622,9 +622,14 @@ void VMManager::Internal::UpdateEmuFolders()

if (EmuFolders::MemoryCards != old_memcards_directory)
{
FileMcd_EmuClose();
FileMcd_EmuOpen();
AutoEject::SetAll();
std::string memcardFilters = "";
if (const GameDatabaseSchema::GameEntry* game = GameDatabase::findGame(s_disc_serial))
{
memcardFilters = game->memcardFiltersAsString();
}

if(!GSDumpReplayer::IsReplayingDump())
FileMcd_Reopen(memcardFilters.empty() ? s_disc_serial : memcardFilters);
}

if (EmuFolders::Textures != old_textures_directory)
Expand Down Expand Up @@ -877,13 +882,6 @@ void VMManager::UpdateDiscDetails(bool booting)
Console.WriteLn(Color_StrongGreen, fmt::format(" Version: {}", s_disc_version));
Console.WriteLn(Color_StrongGreen, fmt::format(" CRC: {:08X}", s_disc_crc));

sioSetGameSerial(memcardFilters.empty() ? s_disc_serial : memcardFilters);

// If we don't reset the timer here, when using folder memcards the reindex will cause an eject,
// which a bunch of games don't like since they access the memory card on boot.
if (booting)
AutoEject::ClearAll();

UpdateGameSettingsLayer();
ApplySettings();

Expand All @@ -898,6 +896,9 @@ void VMManager::UpdateDiscDetails(bool booting)
Achievements::GameChanged(s_disc_crc, s_current_crc);
ReloadPINE();
UpdateDiscordPresence(Achievements::GetRichPresenceString());

if (!GSDumpReplayer::IsReplayingDump())
FileMcd_Reopen(memcardFilters.empty() ? s_disc_serial : memcardFilters);
}

void VMManager::ClearDiscDetails()
Expand Down Expand Up @@ -1140,17 +1141,11 @@ bool VMManager::Initialize(VMBootParameters boot_params)
}
ScopedGuard close_cdvd(&DoCDVDclose);

// Must be before updating serial because of folder memcards.
if (!GSDumpReplayer::IsReplayingDump())
{
Console.WriteLn("Opening Memory cards...");
FileMcd_EmuOpen();
}
ScopedGuard close_memcards(&FileMcd_EmuClose);

// Figure out which game we're running! This also loads game settings.
UpdateDiscDetails(true);

ScopedGuard close_memcards(&FileMcd_EmuClose);

// Read fast boot setting late so it can be overridden per-game.
// ELFs must be fast booted, and GS dumps are never fast booted.
s_fast_boot_requested =
Expand Down Expand Up @@ -1950,7 +1945,9 @@ void VMManager::Internal::EntryPointCompilingOnCPUThread()
HandleELFChange(true);

Patch::ApplyLoadedPatches(Patch::PPT_ONCE_ON_LOAD);

// If the config changes at this point, it's a reset, so the game doesn't currently know about the memcard
// so there's no need to leave the eject running.
FileMcd_CancelEject();
// Toss all the recs, we're going to be executing new code.
SysClearExecutionCache();
}
Expand Down Expand Up @@ -2105,9 +2102,6 @@ void VMManager::CheckForMemoryCardConfigChanges(const Pcsx2Config& old_config)

Console.WriteLn("Updating memory card configuration");

FileMcd_EmuClose();
FileMcd_EmuOpen();

// force card eject when files change
for (u32 port = 0; port < 2; port++)
{
Expand All @@ -2122,7 +2116,6 @@ void VMManager::CheckForMemoryCardConfigChanges(const Pcsx2Config& old_config)
}
}
}

// force reindexing, mc folder code is janky
std::string sioSerial;
{
Expand All @@ -2132,7 +2125,9 @@ void VMManager::CheckForMemoryCardConfigChanges(const Pcsx2Config& old_config)
if (sioSerial.empty())
sioSerial = s_disc_serial;
}
sioSetGameSerial(sioSerial);

if (!GSDumpReplayer::IsReplayingDump())
FileMcd_Reopen(sioSerial);
}

void VMManager::CheckForMiscConfigChanges(const Pcsx2Config& old_config)
Expand Down

0 comments on commit 651d5e7

Please sign in to comment.