mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2025-01-10 08:09:26 +01:00
Merge pull request #8873 from AdmiralCurtiss/gcmemcard-namespace
GCMemcard: Move into a Memcard namespace.
This commit is contained in:
commit
1f505870a9
@ -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
|
||||
|
@ -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" />
|
||||
|
@ -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>
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
33
Source/Core/Core/HW/GCMemcard/GCMemcardBase.h
Normal file
33
Source/Core/Core/HW/GCMemcard/GCMemcardBase.h
Normal 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;
|
||||
};
|
@ -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);
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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();
|
||||
|
@ -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;
|
||||
|
@ -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())
|
||||
|
@ -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;
|
||||
|
@ -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())
|
||||
{
|
||||
|
Loading…
x
Reference in New Issue
Block a user