Merge pull request #8873 from AdmiralCurtiss/gcmemcard-namespace

GCMemcard: Move into a Memcard namespace.
This commit is contained in:
Tilka 2020-06-16 19:55:06 +01:00 committed by GitHub
commit 1f505870a9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
17 changed files with 156 additions and 118 deletions

View File

@ -221,6 +221,7 @@ add_library(core
HW/GCMemcard/GCIFile.h
HW/GCMemcard/GCMemcard.cpp
HW/GCMemcard/GCMemcard.h
HW/GCMemcard/GCMemcardBase.h
HW/GCMemcard/GCMemcardDirectory.cpp
HW/GCMemcard/GCMemcardDirectory.h
HW/GCMemcard/GCMemcardRaw.cpp

View File

@ -514,6 +514,7 @@
<ClInclude Include="HW\GCKeyboardEmu.h" />
<ClInclude Include="HW\GCMemcard\GCIFile.h" />
<ClInclude Include="HW\GCMemcard\GCMemcard.h" />
<ClInclude Include="HW\GCMemcard\GCMemcardBase.h" />
<ClInclude Include="HW\GCMemcard\GCMemcardDirectory.h" />
<ClInclude Include="HW\GCMemcard\GCMemcardRaw.h" />
<ClInclude Include="HW\GCPad.h" />

View File

@ -1245,6 +1245,9 @@
<ClInclude Include="HW\GCMemcard\GCMemcard.h">
<Filter>HW %28Flipper/Hollywood%29\GCMemcard</Filter>
</ClInclude>
<ClInclude Include="HW\GCMemcard\GCMemcardBase.h">
<Filter>HW %28Flipper/Hollywood%29\GCMemcard</Filter>
</ClInclude>
<ClInclude Include="HW\GCMemcard\GCMemcardDirectory.h">
<Filter>HW %28Flipper/Hollywood%29\GCMemcard</Filter>
</ClInclude>

View File

@ -142,7 +142,7 @@ CEXIMemoryCard::CEXIMemoryCard(const int index, bool gciFolder) : card_index(ind
bool useMC251;
IniFile gameIni = SConfig::GetInstance().LoadGameIni();
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)
{
@ -245,7 +245,7 @@ void CEXIMemoryCard::SetupRawMemcard(u16 sizeMb)
SConfig::GetDirectoryForRegion(SConfig::ToGameCubeRegion(SConfig::GetInstance().m_region));
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");
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));
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
@ -561,9 +561,9 @@ void CEXIMemoryCard::DMAWrite(u32 _uAddr, u32 _uSize)
{
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

View File

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

View File

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

View File

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

View File

@ -24,6 +24,8 @@ namespace File
class IOFile;
}
namespace Memcard
{
enum
{
SLOT_A = 0,
@ -158,28 +160,6 @@ constexpr u8 MEMORY_CARD_ICON_FORMAT_CI8_UNIQUE_PALETTE = 3;
// each palette entry is 16 bits in RGB5A3 format
constexpr u32 MEMORY_CARD_CI8_PALETTE_ENTRIES = 256;
class MemoryCardBase
{
public:
explicit MemoryCardBase(int card_index = 0, int size_mbits = MBIT_SIZE_MEMORY_CARD_2043)
: m_card_index(card_index), m_nintendo_card_id(size_mbits)
{
}
virtual ~MemoryCardBase() {}
virtual s32 Read(u32 src_address, s32 length, u8* dest_address) = 0;
virtual s32 Write(u32 dest_address, s32 length, const u8* src_address) = 0;
virtual void ClearBlock(u32 address) = 0;
virtual void ClearAll() = 0;
virtual void DoState(PointerWrap& p) = 0;
u32 GetCardId() const { return m_nintendo_card_id; }
bool IsAddressInBounds(u32 address) const { return address <= (m_memory_card_size - 1); }
protected:
int m_card_index;
u16 m_nintendo_card_id;
u32 m_memory_card_size;
};
struct GCMBlock
{
GCMBlock();
@ -511,3 +491,4 @@ public:
// reads the animation frames
std::optional<std::vector<GCMemcardAnimationFrameRGBA8>> ReadAnimRGBA8(u8 index) const;
};
} // namespace Memcard

View File

@ -0,0 +1,33 @@
// Copyright 2020 Dolphin Emulator Project
// Licensed under GPLv2+
// Refer to the license.txt file included.
#pragma once
#include "Common/CommonTypes.h"
#include "Core/HW/GCMemcard/GCMemcard.h"
class PointerWrap;
class MemoryCardBase
{
public:
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)
{
}
virtual ~MemoryCardBase() = default;
virtual s32 Read(u32 src_address, s32 length, u8* dest_address) = 0;
virtual s32 Write(u32 dest_address, s32 length, const u8* src_address) = 0;
virtual void ClearBlock(u32 address) = 0;
virtual void ClearAll() = 0;
virtual void DoState(PointerWrap& p) = 0;
u32 GetCardId() const { return m_nintendo_card_id; }
bool IsAddressInBounds(u32 address) const { return address <= (m_memory_card_size - 1); }
protected:
int m_card_index;
u16 m_nintendo_card_id;
u32 m_memory_card_size;
};

View File

@ -33,10 +33,10 @@
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
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())
{
@ -80,8 +80,8 @@ bool GCMemcardDirectory::LoadGCI(GCIFile gci)
if (gci.HasCopyProtection())
{
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::PSO_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
@ -110,10 +110,10 @@ std::vector<std::string> GCMemcardDirectory::GetFileNamesForGameID(const std::st
if (!gci_file)
continue;
GCIFile gci;
Memcard::GCIFile gci;
gci.m_filename = file_name;
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;
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)
continue;
const u32 size = num_blocks * BLOCK_SIZE;
const u32 size = num_blocks * Memcard::BLOCK_SIZE;
const u64 file_size = gci_file.GetSize();
if (file_size != size + DENTRY_SIZE)
if (file_size != size + Memcard::DENTRY_SIZE)
continue;
// 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
{
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);
@ -161,11 +161,11 @@ GCMemcardDirectory::GCMemcardDirectory(const std::string& directory, int slot, u
// split up into files for current games we should definitely load,
// and files for other games that we don't care too much about
std::vector<GCIFile> gci_current_game;
std::vector<GCIFile> gci_other_games;
std::vector<Memcard::GCIFile> gci_current_game;
std::vector<Memcard::GCIFile> gci_other_games;
for (const std::string& filename : filenames)
{
GCIFile gci;
Memcard::GCIFile gci;
gci.m_filename = filename;
gci.m_dirty = false;
if (!gci.LoadHeader())
@ -180,11 +180,11 @@ GCMemcardDirectory::GCMemcardDirectory(const std::string& directory, int slot, u
gci_other_games.emplace_back(std::move(gci));
}
m_saves.reserve(DIRLEN);
m_saves.reserve(Memcard::DIRLEN);
// load files for current game
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)))
{
@ -195,11 +195,11 @@ GCMemcardDirectory::GCMemcardDirectory(const std::string& directory, int slot, u
}
// 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;
// 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
if (m_saves.size() > 112)
@ -265,17 +265,17 @@ GCMemcardDirectory::~GCMemcardDirectory()
s32 GCMemcardDirectory::Read(u32 src_address, s32 length, u8* dest_address)
{
s32 block = src_address / BLOCK_SIZE;
u32 offset = src_address % BLOCK_SIZE;
s32 block = src_address / Memcard::BLOCK_SIZE;
u32 offset = src_address % Memcard::BLOCK_SIZE;
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;
// 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");
}
@ -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);
if (length != 0x80)
INFO_LOG(EXPANSIONINTERFACE, "Writing to 0x%x. Length: 0x%x", dest_address, length);
s32 block = dest_address / BLOCK_SIZE;
u32 offset = dest_address % BLOCK_SIZE;
s32 block = dest_address / Memcard::BLOCK_SIZE;
u32 offset = dest_address % Memcard::BLOCK_SIZE;
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;
// 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");
}
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;
while (length > 0)
{
s32 to_write = std::min<s32>(DENTRY_SIZE, length);
s32 to_write = std::min<s32>(Memcard::DENTRY_SIZE, length);
bytes_written +=
DirectoryWrite(dest_address + bytes_written, to_write, src_address + bytes_written);
length -= to_write;
@ -383,20 +383,20 @@ s32 GCMemcardDirectory::Write(u32 dest_address, s32 length, const u8* src_addres
l.unlock();
if (extra)
extra = Write(dest_address + length, extra, src_address + length);
if (offset + length == BLOCK_SIZE)
if (offset + length == Memcard::BLOCK_SIZE)
m_flush_trigger.Set();
return length + extra;
}
void GCMemcardDirectory::ClearBlock(u32 address)
{
if (address % BLOCK_SIZE)
if (address % Memcard::BLOCK_SIZE)
{
PanicAlertT("GCMemcardDirectory: ClearBlock called with invalid block address");
return;
}
u32 block = address / BLOCK_SIZE;
u32 block = address / Memcard::BLOCK_SIZE;
INFO_LOG(EXPANSIONINTERFACE, "Clearing block %u", block);
switch (block)
{
@ -425,34 +425,34 @@ void GCMemcardDirectory::ClearBlock(u32 address)
if (m_last_block == -1)
return;
}
((GCMBlock*)m_last_block_address)->Erase();
((Memcard::GCMBlock*)m_last_block_address)->Erase();
}
inline void GCMemcardDirectory::SyncSaves()
{
Directory* current = &m_dir2;
Memcard::Directory* current = &m_dir2;
if (m_dir1.m_update_counter > m_dir2.m_update_counter)
{
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",
Common::swap32(current->m_dir_entries[i].m_gamecode.data()));
bool added = false;
while (i >= m_saves.size())
{
GCIFile temp;
Memcard::GCIFile temp;
m_saves.push_back(temp);
added = true;
}
if (added ||
memcmp((u8*)&(m_saves[i].m_gci_header), (u8*)&(current->m_dir_entries[i]), DENTRY_SIZE))
if (added || memcmp((u8*)&(m_saves[i].m_gci_header), (u8*)&(current->m_dir_entries[i]),
Memcard::DENTRY_SIZE))
{
m_saves[i].m_dirty = true;
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(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)
{
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",
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_used_blocks.clear();
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)
{
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())
{
@ -530,12 +531,12 @@ inline s32 GCMemcardDirectory::SaveAreaRW(u32 block, bool writing)
s32 GCMemcardDirectory::DirectoryWrite(u32 dest_address, u32 length, const u8* src_address)
{
u32 block = dest_address / BLOCK_SIZE;
u32 offset = dest_address % BLOCK_SIZE;
Directory* dest = (block == 1) ? &m_dir1 : &m_dir2;
u16 Dnum = offset / DENTRY_SIZE;
u32 block = dest_address / Memcard::BLOCK_SIZE;
u32 offset = dest_address % Memcard::BLOCK_SIZE;
Memcard::Directory* dest = (block == 1) ? &m_dir1 : &m_dir2;
u16 Dnum = offset / Memcard::DENTRY_SIZE;
if (Dnum == DIRLEN)
if (Dnum == Memcard::DIRLEN)
{
// first 58 bytes should always be 0xff
// 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)
{
BlockAlloc* current_bat;
Memcard::BlockAlloc* current_bat;
if (m_bat2.m_update_counter > m_bat1.m_update_counter)
current_bat = &m_bat2;
else
@ -586,12 +587,12 @@ void GCMemcardDirectory::FlushToFile()
{
std::unique_lock<std::mutex> l(m_write_mutex);
int errors = 0;
DEntry invalid;
Memcard::DEntry invalid;
for (u16 i = 0; i < m_saves.size(); ++i)
{
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;
if (m_saves[i].m_save_data.empty())
@ -622,8 +623,9 @@ void GCMemcardDirectory::FlushToFile()
File::IOFile gci(m_saves[i].m_filename, "wb");
if (gci)
{
gci.WriteBytes(&m_saves[i].m_gci_header, 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_gci_header, Memcard::DENTRY_SIZE);
gci.WriteBytes(m_saves[i].m_save_data.data(),
Memcard::BLOCK_SIZE * m_saves[i].m_save_data.size());
if (gci.IsGood())
{
@ -681,11 +683,11 @@ void GCMemcardDirectory::DoState(PointerWrap& p)
m_last_block = -1;
m_last_block_address = nullptr;
p.Do(m_save_directory);
p.DoPOD<Header>(m_hdr);
p.DoPOD<Directory>(m_dir1);
p.DoPOD<Directory>(m_dir2);
p.DoPOD<BlockAlloc>(m_bat1);
p.DoPOD<BlockAlloc>(m_bat2);
p.DoPOD<Memcard::Header>(m_hdr);
p.DoPOD<Memcard::Directory>(m_dir1);
p.DoPOD<Memcard::Directory>(m_dir2);
p.DoPOD<Memcard::BlockAlloc>(m_bat1);
p.DoPOD<Memcard::BlockAlloc>(m_bat2);
int num_saves = (int)m_saves.size();
p.Do(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);
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())
{
for (u8 i = 0; i < DIRLEN; i++)
for (u8 i = 0; i < Memcard::DIRLEN; i++)
{
memcard->ExportGci(i, "", directory_name);
}

View File

@ -12,6 +12,7 @@
#include "Common/Event.h"
#include "Core/HW/GCMemcard/GCIFile.h"
#include "Core/HW/GCMemcard/GCMemcard.h"
#include "Core/HW/GCMemcard/GCMemcardBase.h"
// Uncomment this to write the system data of the memorycard from directory to disc
//#define _WRITE_MC_HEADER 1
@ -40,7 +41,7 @@ public:
void DoState(PointerWrap& p) override;
private:
bool LoadGCI(GCIFile gci);
bool LoadGCI(Memcard::GCIFile gci);
inline s32 SaveAreaRW(u32 block, bool writing = false);
// s32 DirectoryRead(u32 offset, u32 length, u8* dest_address);
s32 DirectoryWrite(u32 dest_address, u32 length, const u8* src_address);
@ -51,10 +52,12 @@ private:
s32 m_last_block;
u8* m_last_block_address;
Header m_hdr;
Directory m_dir1, m_dir2;
BlockAlloc m_bat1, m_bat2;
std::vector<GCIFile> m_saves;
Memcard::Header m_hdr;
Memcard::Directory m_dir1;
Memcard::Directory m_dir2;
Memcard::BlockAlloc m_bat1;
Memcard::BlockAlloc m_bat2;
std::vector<Memcard::GCIFile> m_saves;
std::string m_save_directory;
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);
// Fills in MC_HDR_SIZE bytes
GCMemcard::Format(&m_memcard_data[0], m_filename.find(".JAP.raw") != std::string::npos,
size_mbits);
Memcard::GCMemcard::Format(&m_memcard_data[0], m_filename.find(".JAP.raw") != std::string::npos,
size_mbits);
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.");
@ -227,7 +227,7 @@ s32 MemoryCard::Write(u32 dest_address, s32 length, const u8* src_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);
return;
@ -235,7 +235,7 @@ void MemoryCard::ClearBlock(u32 address)
else
{
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();
}

View File

@ -11,6 +11,7 @@
#include "Common/Event.h"
#include "Common/Flag.h"
#include "Core/HW/GCMemcard/GCMemcard.h"
#include "Core/HW/GCMemcard/GCMemcardBase.h"
class PointerWrap;
@ -18,7 +19,7 @@ class MemoryCard : public MemoryCardBase
{
public:
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();
static void CheckPath(std::string& memcardPath, const std::string& gameRegion, bool isSlotA);
void FlushThread();

View File

@ -75,7 +75,7 @@ bool GCMemcardCreateNewDialog::CreateCard()
return false;
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())
{
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")
.arg(memcard->GetFreeBlocks())
.arg(DIRLEN - memcard->GetNumFiles()));
.arg(Memcard::DIRLEN - memcard->GetNumFiles()));
}
void GCMemcardManager::UpdateActions()
@ -268,12 +268,12 @@ void GCMemcardManager::UpdateActions()
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())
{
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
{
@ -336,7 +336,7 @@ void GCMemcardManager::ExportFiles(bool prompt)
// TODO: This is obviously intended to check for success instead.
const auto exportRetval = memcard->ExportGci(file_index, path.toStdString(), "");
if (exportRetval == GCMemcardExportFileRetVal::UNUSED)
if (exportRetval == Memcard::GCMemcardExportFileRetVal::UNUSED)
{
File::Delete(path.toStdString());
}
@ -366,7 +366,7 @@ void GCMemcardManager::ImportFile()
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));
return;
@ -392,7 +392,7 @@ void GCMemcardManager::CopyFiles()
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"));
}
@ -436,7 +436,7 @@ void GCMemcardManager::DeleteFiles()
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"));
}
@ -522,8 +522,8 @@ QPixmap GCMemcardManager::GetBannerFromSaveFile(int file_index, int slot)
QImage image;
if (pxdata)
{
image = QImage(reinterpret_cast<u8*>(pxdata->data()), MEMORY_CARD_BANNER_WIDTH,
MEMORY_CARD_BANNER_HEIGHT, QImage::Format_ARGB32);
image = QImage(reinterpret_cast<u8*>(pxdata->data()), Memcard::MEMORY_CARD_BANNER_WIDTH,
Memcard::MEMORY_CARD_BANNER_HEIGHT, QImage::Format_ARGB32);
}
return QPixmap::fromImage(image);
@ -545,7 +545,8 @@ GCMemcardManager::IconAnimationData GCMemcardManager::GetIconFromSaveFile(int fi
for (size_t f = 0; f < decoded_data->size(); ++f)
{
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));
for (int i = 0; i < (*decoded_data)[f].delay; ++i)
{
@ -579,32 +580,32 @@ GCMemcardManager::IconAnimationData GCMemcardManager::GetIconFromSaveFile(int fi
return frame_data;
}
QString GCMemcardManager::GetErrorMessagesForErrorCode(const GCMemcardErrorCode& code)
QString GCMemcardManager::GetErrorMessagesForErrorCode(const Memcard::GCMemcardErrorCode& code)
{
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."));
if (code.Test(GCMemcardValidityIssues::IO_ERROR))
if (code.Test(Memcard::GCMemcardValidityIssues::IO_ERROR))
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."));
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."));
if (code.Test(GCMemcardValidityIssues::INVALID_CHECKSUM))
if (code.Test(Memcard::GCMemcardValidityIssues::INVALID_CHECKSUM))
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."));
if (code.Test(GCMemcardValidityIssues::DIR_BAT_INCONSISTENT))
if (code.Test(Memcard::GCMemcardValidityIssues::DIR_BAT_INCONSISTENT))
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."));
if (sl.empty())

View File

@ -13,8 +13,11 @@
#include "Common/CommonTypes.h"
namespace Memcard
{
class GCMemcard;
class GCMemcardErrorCode;
} // namespace Memcard
class QDialogButtonBox;
class QGroupBox;
@ -33,7 +36,7 @@ public:
explicit GCMemcardManager(QWidget* parent = nullptr);
~GCMemcardManager();
static QString GetErrorMessagesForErrorCode(const GCMemcardErrorCode& code);
static QString GetErrorMessagesForErrorCode(const Memcard::GCMemcardErrorCode& code);
private:
struct IconAnimationData;
@ -73,7 +76,7 @@ private:
// Slots
static constexpr int SLOT_COUNT = 2;
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<QLineEdit*, SLOT_COUNT> m_slot_file_edit;
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()))
{
auto [error_code, mc] = GCMemcard::Open(filename.toStdString());
auto [error_code, mc] = Memcard::GCMemcard::Open(filename.toStdString());
if (error_code.HasCriticalErrors() || !mc || !mc->IsValid())
{