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 0b95fd1
Show file tree
Hide file tree
Showing 9 changed files with 258 additions and 205 deletions.
255 changes: 125 additions & 130 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
2 changes: 2 additions & 0 deletions pcsx2/Config.h
Original file line number Diff line number Diff line change
Expand Up @@ -1199,8 +1199,10 @@ struct Pcsx2Config
struct McdOptions
{
std::string Filename; // user-configured location of this memory card
std::string LoadedFilename; // user-configured location of this memory card
bool Enabled; // memory card enabled (if false, memcard will not show up in-game)
MemoryCardType Type; // the memory card implementation that should be used
bool ReqReindex;
};

// ------------------------------------------------------------------------
Expand Down
86 changes: 76 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 All @@ -45,6 +46,7 @@ static constexpr int MC2_ERASE_SIZE = 528 * 16;
static const char* s_folder_mem_card_id_file = "_pcsx2_superblock";

bool FileMcd_Open = false;
u32 current_crc = 0;

// ECC code ported from mymc
// https://sourceforge.net/p/mymc-opl/code/ci/master/tree/ps2mc_ecc.py
Expand Down Expand Up @@ -292,14 +294,12 @@ 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, "McdSlot %u [File]: %.*s", slot,
static_cast<int>(str.size()), str.data());
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 @@ -622,6 +622,19 @@ uint FileMcd_ConvertToSlot(uint port, uint slot)
return slot + 4; // multitap 2
}

void FileMcd_EmuInit()
{
for (uint slot = 0; slot < 8; ++slot)
{
EmuConfig.Mcd[slot].Type = MemoryCardType::Empty;
EmuConfig.Mcd[slot].ReqReindex = false;
EmuConfig.Mcd[slot].LoadedFilename = "";
EmuConfig.Mcd[slot].Filename = "";
}

current_crc = 0;
}

void FileMcd_EmuOpen()
{
if(FileMcd_Open)
Expand Down Expand Up @@ -660,6 +673,50 @@ void FileMcd_EmuClose()
Mcd::impl.Close();
}

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

void FileMcd_Reopen(std::string new_serial, u32 crc, bool is_gs_dump)
{
bool require_reindex = current_crc != crc;

current_crc = crc;
// 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.

for (u32 port = 0; port < 2; port++)
for (u32 slot = 0; slot < 4; slot++)
{
const int index = FileMcd_ConvertToSlot(port, slot);

if (EmuConfig.Mcd[index].Enabled)
{
EmuConfig.Mcd[index].ReqReindex |= (EmuConfig.Mcd[index].LoadedFilename != EmuConfig.Mcd[index].Filename) && FileMcd_Open;
require_reindex |= EmuConfig.Mcd[index].ReqReindex;
EmuConfig.Mcd[index].LoadedFilename = EmuConfig.Mcd[index].Filename;
}
}

if (!is_gs_dump)
{
if (require_reindex)
{
Console.WriteLn("Reopening memory cards...");
FileMcd_EmuClose();
FileMcd_EmuOpen();

sioSetGameSerial(new_serial);
}
else
{
Console.WriteLn("Applying changes to memory cards...");
FileMcd_EmuOpen();
}
}
}

s32 FileMcd_IsPresent(uint port, uint slot)
{
const uint combinedSlot = FileMcd_ConvertToSlot(port, slot);
Expand Down Expand Up @@ -776,20 +833,29 @@ 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);
const bool eject_needed = EmuConfig.Mcd[combinedSlot].ReqReindex && EmuConfig.Mcd[combinedSlot].Type != MemoryCardType::Empty;

EmuConfig.Mcd[combinedSlot].ReqReindex = false;

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;
if (!eject_needed)
return -1;
break;
}

return combinedSlot;
}

// --------------------------------------------------------------------------------------
Expand Down
5 changes: 4 additions & 1 deletion pcsx2/MemoryCardFile.h
Original file line number Diff line number Diff line change
Expand Up @@ -45,8 +45,11 @@ extern bool FileMcd_IsMultitapSlot(uint slot);
extern std::string FileMcd_GetDefaultName(uint slot);

uint FileMcd_ConvertToSlot(uint port, uint slot);
void FileMcd_EmuInit();
void FileMcd_EmuOpen();
void FileMcd_EmuClose();
void FileMcd_CancelEject();
void FileMcd_Reopen(std::string new_serial, u32 crc, bool is_gs_dump);
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 +58,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
3 changes: 2 additions & 1 deletion pcsx2/Pcsx2Config.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1373,9 +1373,10 @@ Pcsx2Config::Pcsx2Config()
{
Mcd[slot].Enabled = !FileMcd_IsMultitapSlot(slot); // enables main 2 slots
Mcd[slot].Filename = FileMcd_GetDefaultName(slot);

Mcd[slot].LoadedFilename = Mcd[slot].Filename;
// Folder memory card is autodetected later.
Mcd[slot].Type = MemoryCardType::File;
Mcd[slot].ReqReindex = false;
}

GzipIsoIndexTemplate = "$(f).pindex.tmp";
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

0 comments on commit 0b95fd1

Please sign in to comment.