GCMemcard: Move from global namespace into a Memcard namespace.

This commit is contained in:
Admiral H. Curtiss 2020-06-15 02:09:37 +02:00
parent 2e1bfe073c
commit 914ebdf0dd
14 changed files with 117 additions and 97 deletions

View File

@ -142,7 +142,7 @@ CEXIMemoryCard::CEXIMemoryCard(const int index, bool gciFolder) : card_index(ind
bool useMC251; bool useMC251;
IniFile gameIni = SConfig::GetInstance().LoadGameIni(); IniFile gameIni = SConfig::GetInstance().LoadGameIni();
gameIni.GetOrCreateSection("Core")->Get("MemoryCard251", &useMC251, false); gameIni.GetOrCreateSection("Core")->Get("MemoryCard251", &useMC251, false);
u16 sizeMb = useMC251 ? MBIT_SIZE_MEMORY_CARD_251 : MBIT_SIZE_MEMORY_CARD_2043; u16 sizeMb = useMC251 ? Memcard::MBIT_SIZE_MEMORY_CARD_251 : Memcard::MBIT_SIZE_MEMORY_CARD_2043;
if (gciFolder) if (gciFolder)
{ {
@ -245,7 +245,7 @@ void CEXIMemoryCard::SetupRawMemcard(u16 sizeMb)
SConfig::GetDirectoryForRegion(SConfig::ToGameCubeRegion(SConfig::GetInstance().m_region)); SConfig::GetDirectoryForRegion(SConfig::ToGameCubeRegion(SConfig::GetInstance().m_region));
MemoryCard::CheckPath(filename, region_dir, is_slot_a); MemoryCard::CheckPath(filename, region_dir, is_slot_a);
if (sizeMb == MBIT_SIZE_MEMORY_CARD_251) if (sizeMb == Memcard::MBIT_SIZE_MEMORY_CARD_251)
filename.insert(filename.find_last_of("."), ".251"); filename.insert(filename.find_last_of("."), ".251");
memorycard = std::make_unique<MemoryCard>(filename, card_index, sizeMb); memorycard = std::make_unique<MemoryCard>(filename, card_index, sizeMb);
@ -545,9 +545,9 @@ void CEXIMemoryCard::DMARead(u32 _uAddr, u32 _uSize)
{ {
memorycard->Read(address, _uSize, Memory::GetPointer(_uAddr)); memorycard->Read(address, _uSize, Memory::GetPointer(_uAddr));
if ((address + _uSize) % BLOCK_SIZE == 0) if ((address + _uSize) % Memcard::BLOCK_SIZE == 0)
{ {
INFO_LOG(EXPANSIONINTERFACE, "reading from block: %x", address / BLOCK_SIZE); INFO_LOG(EXPANSIONINTERFACE, "reading from block: %x", address / Memcard::BLOCK_SIZE);
} }
// Schedule transfer complete later based on read speed // Schedule transfer complete later based on read speed
@ -561,9 +561,9 @@ void CEXIMemoryCard::DMAWrite(u32 _uAddr, u32 _uSize)
{ {
memorycard->Write(address, _uSize, Memory::GetPointer(_uAddr)); memorycard->Write(address, _uSize, Memory::GetPointer(_uAddr));
if (((address + _uSize) % BLOCK_SIZE) == 0) if (((address + _uSize) % Memcard::BLOCK_SIZE) == 0)
{ {
INFO_LOG(EXPANSIONINTERFACE, "writing to block: %x", address / BLOCK_SIZE); INFO_LOG(EXPANSIONINTERFACE, "writing to block: %x", address / Memcard::BLOCK_SIZE);
} }
// Schedule transfer complete later based on write speed // Schedule transfer complete later based on write speed

View File

@ -11,6 +11,8 @@
#include "Common/File.h" #include "Common/File.h"
#include "Common/Logging/Log.h" #include "Common/Logging/Log.h"
namespace Memcard
{
bool GCIFile::LoadHeader() bool GCIFile::LoadHeader()
{ {
if (m_filename.empty()) if (m_filename.empty())
@ -100,3 +102,4 @@ void GCIFile::DoState(PointerWrap& p)
} }
p.Do(m_used_blocks); p.Do(m_used_blocks);
} }
} // namespace Memcard

View File

@ -12,6 +12,8 @@
class PointerWrap; class PointerWrap;
namespace Memcard
{
class GCIFile class GCIFile
{ {
public: public:
@ -27,3 +29,4 @@ public:
bool m_dirty; bool m_dirty;
std::string m_filename; std::string m_filename;
}; };
} // namespace Memcard

View File

@ -31,6 +31,8 @@ static constexpr std::optional<u64> BytesToMegabits(u64 bytes)
return megabits; return megabits;
} }
namespace Memcard
{
bool GCMemcardErrorCode::HasCriticalErrors() const bool GCMemcardErrorCode::HasCriticalErrors() const
{ {
return Test(GCMemcardValidityIssues::FAILED_TO_OPEN) || Test(GCMemcardValidityIssues::IO_ERROR) || return Test(GCMemcardValidityIssues::FAILED_TO_OPEN) || Test(GCMemcardValidityIssues::IO_ERROR) ||
@ -1744,3 +1746,4 @@ GCMemcardErrorCode Directory::CheckForErrorsWithBat(const BlockAlloc& bat) const
return error_code; return error_code;
} }
} // namespace Memcard

View File

@ -24,6 +24,8 @@ namespace File
class IOFile; class IOFile;
} }
namespace Memcard
{
enum enum
{ {
SLOT_A = 0, SLOT_A = 0,
@ -489,3 +491,4 @@ public:
// reads the animation frames // reads the animation frames
std::optional<std::vector<GCMemcardAnimationFrameRGBA8>> ReadAnimRGBA8(u8 index) const; std::optional<std::vector<GCMemcardAnimationFrameRGBA8>> ReadAnimRGBA8(u8 index) const;
}; };
} // namespace Memcard

View File

@ -13,7 +13,7 @@ class PointerWrap;
class MemoryCardBase class MemoryCardBase
{ {
public: public:
explicit MemoryCardBase(int card_index = 0, int size_mbits = MBIT_SIZE_MEMORY_CARD_2043) explicit MemoryCardBase(int card_index = 0, int size_mbits = Memcard::MBIT_SIZE_MEMORY_CARD_2043)
: m_card_index(card_index), m_nintendo_card_id(size_mbits) : m_card_index(card_index), m_nintendo_card_id(size_mbits)
{ {
} }

View File

@ -33,10 +33,10 @@
static const char* MC_HDR = "MC_SYSTEM_AREA"; static const char* MC_HDR = "MC_SYSTEM_AREA";
bool GCMemcardDirectory::LoadGCI(GCIFile gci) bool GCMemcardDirectory::LoadGCI(Memcard::GCIFile gci)
{ {
// check if any already loaded file has the same internal name as the new file // check if any already loaded file has the same internal name as the new file
for (const GCIFile& already_loaded_gci : m_saves) for (const Memcard::GCIFile& already_loaded_gci : m_saves)
{ {
if (gci.m_gci_header.GCI_FileName() == already_loaded_gci.m_gci_header.GCI_FileName()) if (gci.m_gci_header.GCI_FileName() == already_loaded_gci.m_gci_header.GCI_FileName())
{ {
@ -80,8 +80,8 @@ bool GCMemcardDirectory::LoadGCI(GCIFile gci)
if (gci.HasCopyProtection()) if (gci.HasCopyProtection())
{ {
GCMemcard::PSO_MakeSaveGameValid(m_hdr, gci.m_gci_header, gci.m_save_data); Memcard::GCMemcard::PSO_MakeSaveGameValid(m_hdr, gci.m_gci_header, gci.m_save_data);
GCMemcard::FZEROGX_MakeSaveGameValid(m_hdr, gci.m_gci_header, gci.m_save_data); Memcard::GCMemcard::FZEROGX_MakeSaveGameValid(m_hdr, gci.m_gci_header, gci.m_save_data);
} }
// actually load save file into memory card // actually load save file into memory card
@ -110,10 +110,10 @@ std::vector<std::string> GCMemcardDirectory::GetFileNamesForGameID(const std::st
if (!gci_file) if (!gci_file)
continue; continue;
GCIFile gci; Memcard::GCIFile gci;
gci.m_filename = file_name; gci.m_filename = file_name;
gci.m_dirty = false; gci.m_dirty = false;
if (!gci_file.ReadBytes(&gci.m_gci_header, DENTRY_SIZE)) if (!gci_file.ReadBytes(&gci.m_gci_header, Memcard::DENTRY_SIZE))
continue; continue;
const std::string gci_filename = gci.m_gci_header.GCI_FileName(); const std::string gci_filename = gci.m_gci_header.GCI_FileName();
@ -126,9 +126,9 @@ std::vector<std::string> GCMemcardDirectory::GetFileNamesForGameID(const std::st
if (num_blocks > 2043) if (num_blocks > 2043)
continue; continue;
const u32 size = num_blocks * BLOCK_SIZE; const u32 size = num_blocks * Memcard::BLOCK_SIZE;
const u64 file_size = gci_file.GetSize(); const u64 file_size = gci_file.GetSize();
if (file_size != size + DENTRY_SIZE) if (file_size != size + Memcard::DENTRY_SIZE)
continue; continue;
// There's technically other available block checks to prevent overfilling the virtual memory // There's technically other available block checks to prevent overfilling the virtual memory
@ -153,7 +153,7 @@ GCMemcardDirectory::GCMemcardDirectory(const std::string& directory, int slot, u
{ {
// Use existing header data if available // Use existing header data if available
{ {
File::IOFile((m_save_directory + MC_HDR), "rb").ReadBytes(&m_hdr, BLOCK_SIZE); File::IOFile((m_save_directory + MC_HDR), "rb").ReadBytes(&m_hdr, Memcard::BLOCK_SIZE);
} }
const bool current_game_only = Config::Get(Config::MAIN_GCI_FOLDER_CURRENT_GAME_ONLY); const bool current_game_only = Config::Get(Config::MAIN_GCI_FOLDER_CURRENT_GAME_ONLY);
@ -161,11 +161,11 @@ GCMemcardDirectory::GCMemcardDirectory(const std::string& directory, int slot, u
// split up into files for current games we should definitely load, // split up into files for current games we should definitely load,
// and files for other games that we don't care too much about // and files for other games that we don't care too much about
std::vector<GCIFile> gci_current_game; std::vector<Memcard::GCIFile> gci_current_game;
std::vector<GCIFile> gci_other_games; std::vector<Memcard::GCIFile> gci_other_games;
for (const std::string& filename : filenames) for (const std::string& filename : filenames)
{ {
GCIFile gci; Memcard::GCIFile gci;
gci.m_filename = filename; gci.m_filename = filename;
gci.m_dirty = false; gci.m_dirty = false;
if (!gci.LoadHeader()) if (!gci.LoadHeader())
@ -180,11 +180,11 @@ GCMemcardDirectory::GCMemcardDirectory(const std::string& directory, int slot, u
gci_other_games.emplace_back(std::move(gci)); gci_other_games.emplace_back(std::move(gci));
} }
m_saves.reserve(DIRLEN); m_saves.reserve(Memcard::DIRLEN);
// load files for current game // load files for current game
size_t failed_loads_current_game = 0; size_t failed_loads_current_game = 0;
for (GCIFile& gci : gci_current_game) for (Memcard::GCIFile& gci : gci_current_game)
{ {
if (!LoadGCI(std::move(gci))) if (!LoadGCI(std::move(gci)))
{ {
@ -195,11 +195,11 @@ GCMemcardDirectory::GCMemcardDirectory(const std::string& directory, int slot, u
} }
// leave about 10% of free space on the card if possible // leave about 10% of free space on the card if possible
const int total_blocks = m_hdr.m_size_mb * MBIT_TO_BLOCKS - MC_FST_BLOCKS; const int total_blocks = m_hdr.m_size_mb * Memcard::MBIT_TO_BLOCKS - Memcard::MC_FST_BLOCKS;
const int reserved_blocks = total_blocks / 10; const int reserved_blocks = total_blocks / 10;
// load files for other games // load files for other games
for (GCIFile& gci : gci_other_games) for (Memcard::GCIFile& gci : gci_other_games)
{ {
// leave some free file entries for new saves that might be created // leave some free file entries for new saves that might be created
if (m_saves.size() > 112) if (m_saves.size() > 112)
@ -265,17 +265,17 @@ GCMemcardDirectory::~GCMemcardDirectory()
s32 GCMemcardDirectory::Read(u32 src_address, s32 length, u8* dest_address) s32 GCMemcardDirectory::Read(u32 src_address, s32 length, u8* dest_address)
{ {
s32 block = src_address / BLOCK_SIZE; s32 block = src_address / Memcard::BLOCK_SIZE;
u32 offset = src_address % BLOCK_SIZE; u32 offset = src_address % Memcard::BLOCK_SIZE;
s32 extra = 0; // used for read calls that are across multiple blocks s32 extra = 0; // used for read calls that are across multiple blocks
if (offset + length > BLOCK_SIZE) if (offset + length > Memcard::BLOCK_SIZE)
{ {
extra = length + offset - BLOCK_SIZE; extra = length + offset - Memcard::BLOCK_SIZE;
length -= extra; length -= extra;
// verify that we haven't calculated a length beyond BLOCK_SIZE // verify that we haven't calculated a length beyond BLOCK_SIZE
DEBUG_ASSERT_MSG(EXPANSIONINTERFACE, (src_address + length) % BLOCK_SIZE == 0, DEBUG_ASSERT_MSG(EXPANSIONINTERFACE, (src_address + length) % Memcard::BLOCK_SIZE == 0,
"Memcard directory Read Logic Error"); "Memcard directory Read Logic Error");
} }
@ -325,17 +325,17 @@ s32 GCMemcardDirectory::Write(u32 dest_address, s32 length, const u8* src_addres
std::unique_lock<std::mutex> l(m_write_mutex); std::unique_lock<std::mutex> l(m_write_mutex);
if (length != 0x80) if (length != 0x80)
INFO_LOG(EXPANSIONINTERFACE, "Writing to 0x%x. Length: 0x%x", dest_address, length); INFO_LOG(EXPANSIONINTERFACE, "Writing to 0x%x. Length: 0x%x", dest_address, length);
s32 block = dest_address / BLOCK_SIZE; s32 block = dest_address / Memcard::BLOCK_SIZE;
u32 offset = dest_address % BLOCK_SIZE; u32 offset = dest_address % Memcard::BLOCK_SIZE;
s32 extra = 0; // used for write calls that are across multiple blocks s32 extra = 0; // used for write calls that are across multiple blocks
if (offset + length > BLOCK_SIZE) if (offset + length > Memcard::BLOCK_SIZE)
{ {
extra = length + offset - BLOCK_SIZE; extra = length + offset - Memcard::BLOCK_SIZE;
length -= extra; length -= extra;
// verify that we haven't calculated a length beyond BLOCK_SIZE // verify that we haven't calculated a length beyond BLOCK_SIZE
DEBUG_ASSERT_MSG(EXPANSIONINTERFACE, (dest_address + length) % BLOCK_SIZE == 0, DEBUG_ASSERT_MSG(EXPANSIONINTERFACE, (dest_address + length) % Memcard::BLOCK_SIZE == 0,
"Memcard directory Write Logic Error"); "Memcard directory Write Logic Error");
} }
if (m_last_block != block) if (m_last_block != block)
@ -353,7 +353,7 @@ s32 GCMemcardDirectory::Write(u32 dest_address, s32 length, const u8* src_addres
s32 bytes_written = 0; s32 bytes_written = 0;
while (length > 0) while (length > 0)
{ {
s32 to_write = std::min<s32>(DENTRY_SIZE, length); s32 to_write = std::min<s32>(Memcard::DENTRY_SIZE, length);
bytes_written += bytes_written +=
DirectoryWrite(dest_address + bytes_written, to_write, src_address + bytes_written); DirectoryWrite(dest_address + bytes_written, to_write, src_address + bytes_written);
length -= to_write; length -= to_write;
@ -383,20 +383,20 @@ s32 GCMemcardDirectory::Write(u32 dest_address, s32 length, const u8* src_addres
l.unlock(); l.unlock();
if (extra) if (extra)
extra = Write(dest_address + length, extra, src_address + length); extra = Write(dest_address + length, extra, src_address + length);
if (offset + length == BLOCK_SIZE) if (offset + length == Memcard::BLOCK_SIZE)
m_flush_trigger.Set(); m_flush_trigger.Set();
return length + extra; return length + extra;
} }
void GCMemcardDirectory::ClearBlock(u32 address) void GCMemcardDirectory::ClearBlock(u32 address)
{ {
if (address % BLOCK_SIZE) if (address % Memcard::BLOCK_SIZE)
{ {
PanicAlertT("GCMemcardDirectory: ClearBlock called with invalid block address"); PanicAlertT("GCMemcardDirectory: ClearBlock called with invalid block address");
return; return;
} }
u32 block = address / BLOCK_SIZE; u32 block = address / Memcard::BLOCK_SIZE;
INFO_LOG(EXPANSIONINTERFACE, "Clearing block %u", block); INFO_LOG(EXPANSIONINTERFACE, "Clearing block %u", block);
switch (block) switch (block)
{ {
@ -425,34 +425,34 @@ void GCMemcardDirectory::ClearBlock(u32 address)
if (m_last_block == -1) if (m_last_block == -1)
return; return;
} }
((GCMBlock*)m_last_block_address)->Erase(); ((Memcard::GCMBlock*)m_last_block_address)->Erase();
} }
inline void GCMemcardDirectory::SyncSaves() inline void GCMemcardDirectory::SyncSaves()
{ {
Directory* current = &m_dir2; Memcard::Directory* current = &m_dir2;
if (m_dir1.m_update_counter > m_dir2.m_update_counter) if (m_dir1.m_update_counter > m_dir2.m_update_counter)
{ {
current = &m_dir1; current = &m_dir1;
} }
for (u32 i = 0; i < DIRLEN; ++i) for (u32 i = 0; i < Memcard::DIRLEN; ++i)
{ {
if (current->m_dir_entries[i].m_gamecode != DEntry::UNINITIALIZED_GAMECODE) if (current->m_dir_entries[i].m_gamecode != Memcard::DEntry::UNINITIALIZED_GAMECODE)
{ {
INFO_LOG(EXPANSIONINTERFACE, "Syncing save 0x%x", INFO_LOG(EXPANSIONINTERFACE, "Syncing save 0x%x",
Common::swap32(current->m_dir_entries[i].m_gamecode.data())); Common::swap32(current->m_dir_entries[i].m_gamecode.data()));
bool added = false; bool added = false;
while (i >= m_saves.size()) while (i >= m_saves.size())
{ {
GCIFile temp; Memcard::GCIFile temp;
m_saves.push_back(temp); m_saves.push_back(temp);
added = true; added = true;
} }
if (added || if (added || memcmp((u8*)&(m_saves[i].m_gci_header), (u8*)&(current->m_dir_entries[i]),
memcmp((u8*)&(m_saves[i].m_gci_header), (u8*)&(current->m_dir_entries[i]), DENTRY_SIZE)) Memcard::DENTRY_SIZE))
{ {
m_saves[i].m_dirty = true; m_saves[i].m_dirty = true;
const u32 gamecode = Common::swap32(m_saves[i].m_gci_header.m_gamecode.data()); const u32 gamecode = Common::swap32(m_saves[i].m_gci_header.m_gamecode.data());
@ -466,7 +466,8 @@ inline void GCMemcardDirectory::SyncSaves()
Common::swap32(m_saves[i].m_gci_header.m_gamecode.data()), Common::swap32(m_saves[i].m_gci_header.m_gamecode.data()),
Common::swap32(current->m_dir_entries[i].m_gamecode.data())); Common::swap32(current->m_dir_entries[i].m_gamecode.data()));
} }
memcpy((u8*)&(m_saves[i].m_gci_header), (u8*)&(current->m_dir_entries[i]), DENTRY_SIZE); memcpy((u8*)&(m_saves[i].m_gci_header), (u8*)&(current->m_dir_entries[i]),
Memcard::DENTRY_SIZE);
if (old_start != new_start) if (old_start != new_start)
{ {
INFO_LOG(EXPANSIONINTERFACE, "Save moved from 0x%x to 0x%x", old_start, new_start); INFO_LOG(EXPANSIONINTERFACE, "Save moved from 0x%x to 0x%x", old_start, new_start);
@ -483,7 +484,7 @@ inline void GCMemcardDirectory::SyncSaves()
{ {
INFO_LOG(EXPANSIONINTERFACE, "Clearing and/or deleting save 0x%x", INFO_LOG(EXPANSIONINTERFACE, "Clearing and/or deleting save 0x%x",
Common::swap32(m_saves[i].m_gci_header.m_gamecode.data())); Common::swap32(m_saves[i].m_gci_header.m_gamecode.data()));
m_saves[i].m_gci_header.m_gamecode = DEntry::UNINITIALIZED_GAMECODE; m_saves[i].m_gci_header.m_gamecode = Memcard::DEntry::UNINITIALIZED_GAMECODE;
m_saves[i].m_save_data.clear(); m_saves[i].m_save_data.clear();
m_saves[i].m_used_blocks.clear(); m_saves[i].m_used_blocks.clear();
m_saves[i].m_dirty = true; m_saves[i].m_dirty = true;
@ -494,7 +495,7 @@ inline s32 GCMemcardDirectory::SaveAreaRW(u32 block, bool writing)
{ {
for (u16 i = 0; i < m_saves.size(); ++i) for (u16 i = 0; i < m_saves.size(); ++i)
{ {
if (m_saves[i].m_gci_header.m_gamecode != DEntry::UNINITIALIZED_GAMECODE) if (m_saves[i].m_gci_header.m_gamecode != Memcard::DEntry::UNINITIALIZED_GAMECODE)
{ {
if (m_saves[i].m_used_blocks.empty()) if (m_saves[i].m_used_blocks.empty())
{ {
@ -530,12 +531,12 @@ inline s32 GCMemcardDirectory::SaveAreaRW(u32 block, bool writing)
s32 GCMemcardDirectory::DirectoryWrite(u32 dest_address, u32 length, const u8* src_address) s32 GCMemcardDirectory::DirectoryWrite(u32 dest_address, u32 length, const u8* src_address)
{ {
u32 block = dest_address / BLOCK_SIZE; u32 block = dest_address / Memcard::BLOCK_SIZE;
u32 offset = dest_address % BLOCK_SIZE; u32 offset = dest_address % Memcard::BLOCK_SIZE;
Directory* dest = (block == 1) ? &m_dir1 : &m_dir2; Memcard::Directory* dest = (block == 1) ? &m_dir1 : &m_dir2;
u16 Dnum = offset / DENTRY_SIZE; u16 Dnum = offset / Memcard::DENTRY_SIZE;
if (Dnum == DIRLEN) if (Dnum == Memcard::DIRLEN)
{ {
// first 58 bytes should always be 0xff // first 58 bytes should always be 0xff
// needed to update the update ctr, checksums // needed to update the update ctr, checksums
@ -551,7 +552,7 @@ s32 GCMemcardDirectory::DirectoryWrite(u32 dest_address, u32 length, const u8* s
bool GCMemcardDirectory::SetUsedBlocks(int save_index) bool GCMemcardDirectory::SetUsedBlocks(int save_index)
{ {
BlockAlloc* current_bat; Memcard::BlockAlloc* current_bat;
if (m_bat2.m_update_counter > m_bat1.m_update_counter) if (m_bat2.m_update_counter > m_bat1.m_update_counter)
current_bat = &m_bat2; current_bat = &m_bat2;
else else
@ -586,12 +587,12 @@ void GCMemcardDirectory::FlushToFile()
{ {
std::unique_lock<std::mutex> l(m_write_mutex); std::unique_lock<std::mutex> l(m_write_mutex);
int errors = 0; int errors = 0;
DEntry invalid; Memcard::DEntry invalid;
for (u16 i = 0; i < m_saves.size(); ++i) for (u16 i = 0; i < m_saves.size(); ++i)
{ {
if (m_saves[i].m_dirty) if (m_saves[i].m_dirty)
{ {
if (m_saves[i].m_gci_header.m_gamecode != DEntry::UNINITIALIZED_GAMECODE) if (m_saves[i].m_gci_header.m_gamecode != Memcard::DEntry::UNINITIALIZED_GAMECODE)
{ {
m_saves[i].m_dirty = false; m_saves[i].m_dirty = false;
if (m_saves[i].m_save_data.empty()) if (m_saves[i].m_save_data.empty())
@ -622,8 +623,9 @@ void GCMemcardDirectory::FlushToFile()
File::IOFile gci(m_saves[i].m_filename, "wb"); File::IOFile gci(m_saves[i].m_filename, "wb");
if (gci) if (gci)
{ {
gci.WriteBytes(&m_saves[i].m_gci_header, DENTRY_SIZE); gci.WriteBytes(&m_saves[i].m_gci_header, Memcard::DENTRY_SIZE);
gci.WriteBytes(m_saves[i].m_save_data.data(), BLOCK_SIZE * m_saves[i].m_save_data.size()); gci.WriteBytes(m_saves[i].m_save_data.data(),
Memcard::BLOCK_SIZE * m_saves[i].m_save_data.size());
if (gci.IsGood()) if (gci.IsGood())
{ {
@ -681,11 +683,11 @@ void GCMemcardDirectory::DoState(PointerWrap& p)
m_last_block = -1; m_last_block = -1;
m_last_block_address = nullptr; m_last_block_address = nullptr;
p.Do(m_save_directory); p.Do(m_save_directory);
p.DoPOD<Header>(m_hdr); p.DoPOD<Memcard::Header>(m_hdr);
p.DoPOD<Directory>(m_dir1); p.DoPOD<Memcard::Directory>(m_dir1);
p.DoPOD<Directory>(m_dir2); p.DoPOD<Memcard::Directory>(m_dir2);
p.DoPOD<BlockAlloc>(m_bat1); p.DoPOD<Memcard::BlockAlloc>(m_bat1);
p.DoPOD<BlockAlloc>(m_bat2); p.DoPOD<Memcard::BlockAlloc>(m_bat2);
int num_saves = (int)m_saves.size(); int num_saves = (int)m_saves.size();
p.Do(num_saves); p.Do(num_saves);
m_saves.resize(num_saves); m_saves.resize(num_saves);
@ -702,10 +704,10 @@ void MigrateFromMemcardFile(const std::string& directory_name, int card_index)
Config::Get(Config::MAIN_MEMCARD_B_PATH); Config::Get(Config::MAIN_MEMCARD_B_PATH);
if (File::Exists(ini_memcard)) if (File::Exists(ini_memcard))
{ {
auto [error_code, memcard] = GCMemcard::Open(ini_memcard.c_str()); auto [error_code, memcard] = Memcard::GCMemcard::Open(ini_memcard.c_str());
if (!error_code.HasCriticalErrors() && memcard && memcard->IsValid()) if (!error_code.HasCriticalErrors() && memcard && memcard->IsValid())
{ {
for (u8 i = 0; i < DIRLEN; i++) for (u8 i = 0; i < Memcard::DIRLEN; i++)
{ {
memcard->ExportGci(i, "", directory_name); memcard->ExportGci(i, "", directory_name);
} }

View File

@ -41,7 +41,7 @@ public:
void DoState(PointerWrap& p) override; void DoState(PointerWrap& p) override;
private: private:
bool LoadGCI(GCIFile gci); bool LoadGCI(Memcard::GCIFile gci);
inline s32 SaveAreaRW(u32 block, bool writing = false); inline s32 SaveAreaRW(u32 block, bool writing = false);
// s32 DirectoryRead(u32 offset, u32 length, u8* dest_address); // s32 DirectoryRead(u32 offset, u32 length, u8* dest_address);
s32 DirectoryWrite(u32 dest_address, u32 length, const u8* src_address); s32 DirectoryWrite(u32 dest_address, u32 length, const u8* src_address);
@ -52,10 +52,12 @@ private:
s32 m_last_block; s32 m_last_block;
u8* m_last_block_address; u8* m_last_block_address;
Header m_hdr; Memcard::Header m_hdr;
Directory m_dir1, m_dir2; Memcard::Directory m_dir1;
BlockAlloc m_bat1, m_bat2; Memcard::Directory m_dir2;
std::vector<GCIFile> m_saves; Memcard::BlockAlloc m_bat1;
Memcard::BlockAlloc m_bat2;
std::vector<Memcard::GCIFile> m_saves;
std::string m_save_directory; std::string m_save_directory;
Common::Event m_flush_trigger; Common::Event m_flush_trigger;

View File

@ -52,8 +52,8 @@ MemoryCard::MemoryCard(const std::string& filename, int card_index, u16 size_mbi
m_memcard_data = std::make_unique<u8[]>(m_memory_card_size); m_memcard_data = std::make_unique<u8[]>(m_memory_card_size);
// Fills in MC_HDR_SIZE bytes // Fills in MC_HDR_SIZE bytes
GCMemcard::Format(&m_memcard_data[0], m_filename.find(".JAP.raw") != std::string::npos, Memcard::GCMemcard::Format(&m_memcard_data[0], m_filename.find(".JAP.raw") != std::string::npos,
size_mbits); size_mbits);
memset(&m_memcard_data[MC_HDR_SIZE], 0xFF, m_memory_card_size - MC_HDR_SIZE); memset(&m_memcard_data[MC_HDR_SIZE], 0xFF, m_memory_card_size - MC_HDR_SIZE);
INFO_LOG(EXPANSIONINTERFACE, "No memory card found. A new one was created instead."); INFO_LOG(EXPANSIONINTERFACE, "No memory card found. A new one was created instead.");
@ -227,7 +227,7 @@ s32 MemoryCard::Write(u32 dest_address, s32 length, const u8* src_address)
void MemoryCard::ClearBlock(u32 address) void MemoryCard::ClearBlock(u32 address)
{ {
if (address & (BLOCK_SIZE - 1) || !IsAddressInBounds(address)) if (address & (Memcard::BLOCK_SIZE - 1) || !IsAddressInBounds(address))
{ {
PanicAlertT("MemoryCard: ClearBlock called on invalid address (0x%x)", address); PanicAlertT("MemoryCard: ClearBlock called on invalid address (0x%x)", address);
return; return;
@ -235,7 +235,7 @@ void MemoryCard::ClearBlock(u32 address)
else else
{ {
std::unique_lock<std::mutex> l(m_flush_mutex); std::unique_lock<std::mutex> l(m_flush_mutex);
memset(&m_memcard_data[address], 0xFF, BLOCK_SIZE); memset(&m_memcard_data[address], 0xFF, Memcard::BLOCK_SIZE);
} }
MakeDirty(); MakeDirty();
} }

View File

@ -19,7 +19,7 @@ class MemoryCard : public MemoryCardBase
{ {
public: public:
MemoryCard(const std::string& filename, int card_index, MemoryCard(const std::string& filename, int card_index,
u16 size_mbits = MBIT_SIZE_MEMORY_CARD_2043); u16 size_mbits = Memcard::MBIT_SIZE_MEMORY_CARD_2043);
~MemoryCard(); ~MemoryCard();
static void CheckPath(std::string& memcardPath, const std::string& gameRegion, bool isSlotA); static void CheckPath(std::string& memcardPath, const std::string& gameRegion, bool isSlotA);
void FlushThread(); void FlushThread();

View File

@ -75,7 +75,7 @@ bool GCMemcardCreateNewDialog::CreateCard()
return false; return false;
const std::string p = path.toStdString(); const std::string p = path.toStdString();
auto memcard = GCMemcard::Create(p, size, is_shift_jis); auto memcard = Memcard::GCMemcard::Create(p, size, is_shift_jis);
if (memcard && memcard->Save()) if (memcard && memcard->Save())
{ {
m_card_path = p; m_card_path = p;

View File

@ -248,7 +248,7 @@ void GCMemcardManager::UpdateSlotTable(int slot)
m_slot_stat_label[slot]->setText(tr("%1 Free Blocks; %2 Free Dir Entries") m_slot_stat_label[slot]->setText(tr("%1 Free Blocks; %2 Free Dir Entries")
.arg(memcard->GetFreeBlocks()) .arg(memcard->GetFreeBlocks())
.arg(DIRLEN - memcard->GetNumFiles())); .arg(Memcard::DIRLEN - memcard->GetNumFiles()));
} }
void GCMemcardManager::UpdateActions() void GCMemcardManager::UpdateActions()
@ -268,12 +268,12 @@ void GCMemcardManager::UpdateActions()
void GCMemcardManager::SetSlotFile(int slot, QString path) void GCMemcardManager::SetSlotFile(int slot, QString path)
{ {
auto [error_code, memcard] = GCMemcard::Open(path.toStdString()); auto [error_code, memcard] = Memcard::GCMemcard::Open(path.toStdString());
if (!error_code.HasCriticalErrors() && memcard && memcard->IsValid()) if (!error_code.HasCriticalErrors() && memcard && memcard->IsValid())
{ {
m_slot_file_edit[slot]->setText(path); m_slot_file_edit[slot]->setText(path);
m_slot_memcard[slot] = std::make_unique<GCMemcard>(std::move(*memcard)); m_slot_memcard[slot] = std::make_unique<Memcard::GCMemcard>(std::move(*memcard));
} }
else else
{ {
@ -336,7 +336,7 @@ void GCMemcardManager::ExportFiles(bool prompt)
// TODO: This is obviously intended to check for success instead. // TODO: This is obviously intended to check for success instead.
const auto exportRetval = memcard->ExportGci(file_index, path.toStdString(), ""); const auto exportRetval = memcard->ExportGci(file_index, path.toStdString(), "");
if (exportRetval == GCMemcardExportFileRetVal::UNUSED) if (exportRetval == Memcard::GCMemcardExportFileRetVal::UNUSED)
{ {
File::Delete(path.toStdString()); File::Delete(path.toStdString());
} }
@ -366,7 +366,7 @@ void GCMemcardManager::ImportFile()
const auto result = m_slot_memcard[m_active_slot]->ImportGci(path.toStdString()); const auto result = m_slot_memcard[m_active_slot]->ImportGci(path.toStdString());
if (result != GCMemcardImportFileRetVal::SUCCESS) if (result != Memcard::GCMemcardImportFileRetVal::SUCCESS)
{ {
ModalMessageBox::critical(this, tr("Import failed"), tr("Failed to import \"%1\".").arg(path)); ModalMessageBox::critical(this, tr("Import failed"), tr("Failed to import \"%1\".").arg(path));
return; return;
@ -392,7 +392,7 @@ void GCMemcardManager::CopyFiles()
const auto result = m_slot_memcard[!m_active_slot]->CopyFrom(*memcard, file_index); const auto result = m_slot_memcard[!m_active_slot]->CopyFrom(*memcard, file_index);
if (result != GCMemcardImportFileRetVal::SUCCESS) if (result != Memcard::GCMemcardImportFileRetVal::SUCCESS)
{ {
ModalMessageBox::warning(this, tr("Copy failed"), tr("Failed to copy file")); ModalMessageBox::warning(this, tr("Copy failed"), tr("Failed to copy file"));
} }
@ -436,7 +436,7 @@ void GCMemcardManager::DeleteFiles()
for (int file_index : file_indices) for (int file_index : file_indices)
{ {
if (memcard->RemoveFile(file_index) != GCMemcardRemoveFileRetVal::SUCCESS) if (memcard->RemoveFile(file_index) != Memcard::GCMemcardRemoveFileRetVal::SUCCESS)
{ {
ModalMessageBox::warning(this, tr("Remove failed"), tr("Failed to remove file")); ModalMessageBox::warning(this, tr("Remove failed"), tr("Failed to remove file"));
} }
@ -522,8 +522,8 @@ QPixmap GCMemcardManager::GetBannerFromSaveFile(int file_index, int slot)
QImage image; QImage image;
if (pxdata) if (pxdata)
{ {
image = QImage(reinterpret_cast<u8*>(pxdata->data()), MEMORY_CARD_BANNER_WIDTH, image = QImage(reinterpret_cast<u8*>(pxdata->data()), Memcard::MEMORY_CARD_BANNER_WIDTH,
MEMORY_CARD_BANNER_HEIGHT, QImage::Format_ARGB32); Memcard::MEMORY_CARD_BANNER_HEIGHT, QImage::Format_ARGB32);
} }
return QPixmap::fromImage(image); return QPixmap::fromImage(image);
@ -545,7 +545,8 @@ GCMemcardManager::IconAnimationData GCMemcardManager::GetIconFromSaveFile(int fi
for (size_t f = 0; f < decoded_data->size(); ++f) for (size_t f = 0; f < decoded_data->size(); ++f)
{ {
QImage img(reinterpret_cast<const u8*>((*decoded_data)[f].image_data.data()), QImage img(reinterpret_cast<const u8*>((*decoded_data)[f].image_data.data()),
MEMORY_CARD_ICON_WIDTH, MEMORY_CARD_ICON_HEIGHT, QImage::Format_ARGB32); Memcard::MEMORY_CARD_ICON_WIDTH, Memcard::MEMORY_CARD_ICON_HEIGHT,
QImage::Format_ARGB32);
frame_data.m_frames.push_back(QPixmap::fromImage(img)); frame_data.m_frames.push_back(QPixmap::fromImage(img));
for (int i = 0; i < (*decoded_data)[f].delay; ++i) for (int i = 0; i < (*decoded_data)[f].delay; ++i)
{ {
@ -579,32 +580,32 @@ GCMemcardManager::IconAnimationData GCMemcardManager::GetIconFromSaveFile(int fi
return frame_data; return frame_data;
} }
QString GCMemcardManager::GetErrorMessagesForErrorCode(const GCMemcardErrorCode& code) QString GCMemcardManager::GetErrorMessagesForErrorCode(const Memcard::GCMemcardErrorCode& code)
{ {
QStringList sl; QStringList sl;
if (code.Test(GCMemcardValidityIssues::FAILED_TO_OPEN)) if (code.Test(Memcard::GCMemcardValidityIssues::FAILED_TO_OPEN))
sl.push_back(tr("Couldn't open file.")); sl.push_back(tr("Couldn't open file."));
if (code.Test(GCMemcardValidityIssues::IO_ERROR)) if (code.Test(Memcard::GCMemcardValidityIssues::IO_ERROR))
sl.push_back(tr("Couldn't read file.")); sl.push_back(tr("Couldn't read file."));
if (code.Test(GCMemcardValidityIssues::INVALID_CARD_SIZE)) if (code.Test(Memcard::GCMemcardValidityIssues::INVALID_CARD_SIZE))
sl.push_back(tr("Filesize does not match any known GameCube Memory Card size.")); sl.push_back(tr("Filesize does not match any known GameCube Memory Card size."));
if (code.Test(GCMemcardValidityIssues::MISMATCHED_CARD_SIZE)) if (code.Test(Memcard::GCMemcardValidityIssues::MISMATCHED_CARD_SIZE))
sl.push_back(tr("Filesize in header mismatches actual card size.")); sl.push_back(tr("Filesize in header mismatches actual card size."));
if (code.Test(GCMemcardValidityIssues::INVALID_CHECKSUM)) if (code.Test(Memcard::GCMemcardValidityIssues::INVALID_CHECKSUM))
sl.push_back(tr("Invalid checksums.")); sl.push_back(tr("Invalid checksums."));
if (code.Test(GCMemcardValidityIssues::FREE_BLOCK_MISMATCH)) if (code.Test(Memcard::GCMemcardValidityIssues::FREE_BLOCK_MISMATCH))
sl.push_back(tr("Mismatch between free block count in header and actually unused blocks.")); sl.push_back(tr("Mismatch between free block count in header and actually unused blocks."));
if (code.Test(GCMemcardValidityIssues::DIR_BAT_INCONSISTENT)) if (code.Test(Memcard::GCMemcardValidityIssues::DIR_BAT_INCONSISTENT))
sl.push_back(tr("Mismatch between internal data structures.")); sl.push_back(tr("Mismatch between internal data structures."));
if (code.Test(GCMemcardValidityIssues::DATA_IN_UNUSED_AREA)) if (code.Test(Memcard::GCMemcardValidityIssues::DATA_IN_UNUSED_AREA))
sl.push_back(tr("Data in area of file that should be unused.")); sl.push_back(tr("Data in area of file that should be unused."));
if (sl.empty()) if (sl.empty())

View File

@ -13,8 +13,11 @@
#include "Common/CommonTypes.h" #include "Common/CommonTypes.h"
namespace Memcard
{
class GCMemcard; class GCMemcard;
class GCMemcardErrorCode; class GCMemcardErrorCode;
} // namespace Memcard
class QDialogButtonBox; class QDialogButtonBox;
class QGroupBox; class QGroupBox;
@ -33,7 +36,7 @@ public:
explicit GCMemcardManager(QWidget* parent = nullptr); explicit GCMemcardManager(QWidget* parent = nullptr);
~GCMemcardManager(); ~GCMemcardManager();
static QString GetErrorMessagesForErrorCode(const GCMemcardErrorCode& code); static QString GetErrorMessagesForErrorCode(const Memcard::GCMemcardErrorCode& code);
private: private:
struct IconAnimationData; struct IconAnimationData;
@ -73,7 +76,7 @@ private:
// Slots // Slots
static constexpr int SLOT_COUNT = 2; static constexpr int SLOT_COUNT = 2;
std::array<std::vector<IconAnimationData>, SLOT_COUNT> m_slot_active_icons; std::array<std::vector<IconAnimationData>, SLOT_COUNT> m_slot_active_icons;
std::array<std::unique_ptr<GCMemcard>, SLOT_COUNT> m_slot_memcard; std::array<std::unique_ptr<Memcard::GCMemcard>, SLOT_COUNT> m_slot_memcard;
std::array<QGroupBox*, SLOT_COUNT> m_slot_group; std::array<QGroupBox*, SLOT_COUNT> m_slot_group;
std::array<QLineEdit*, SLOT_COUNT> m_slot_file_edit; std::array<QLineEdit*, SLOT_COUNT> m_slot_file_edit;
std::array<QPushButton*, SLOT_COUNT> m_slot_open_button; std::array<QPushButton*, SLOT_COUNT> m_slot_open_button;

View File

@ -210,7 +210,7 @@ void GameCubePane::OnConfigPressed(int slot)
{ {
if (File::Exists(filename.toStdString())) if (File::Exists(filename.toStdString()))
{ {
auto [error_code, mc] = GCMemcard::Open(filename.toStdString()); auto [error_code, mc] = Memcard::GCMemcard::Open(filename.toStdString());
if (error_code.HasCriticalErrors() || !mc || !mc->IsValid()) if (error_code.HasCriticalErrors() || !mc || !mc->IsValid())
{ {