mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2024-11-14 13:27:45 -07:00
GCMemcardDirectory: Decode and strip strings for GCI filenames.
This commit is contained in:
parent
c517e92719
commit
4b0312ecf8
@ -304,7 +304,7 @@ void GCMemcard::UpdateBat(const BlockAlloc& bat)
|
||||
|
||||
bool GCMemcard::IsShiftJIS() const
|
||||
{
|
||||
return m_header_block.m_data.m_encoding != 0;
|
||||
return m_header_block.IsShiftJIS();
|
||||
}
|
||||
|
||||
bool GCMemcard::Save()
|
||||
@ -1274,15 +1274,6 @@ DEntry::DEntry()
|
||||
memset(reinterpret_cast<u8*>(this), 0xFF, DENTRY_SIZE);
|
||||
}
|
||||
|
||||
std::string DEntry::GCI_FileName() const
|
||||
{
|
||||
std::string filename =
|
||||
std::string(reinterpret_cast<const char*>(m_makercode.data()), m_makercode.size()) + '-' +
|
||||
std::string(reinterpret_cast<const char*>(m_gamecode.data()), m_gamecode.size()) + '-' +
|
||||
reinterpret_cast<const char*>(m_filename.data()) + ".gci";
|
||||
return Common::EscapeFileName(filename);
|
||||
}
|
||||
|
||||
void Header::FixChecksums()
|
||||
{
|
||||
std::tie(m_checksum, m_checksum_inv) = CalculateChecksums();
|
||||
@ -1324,6 +1315,11 @@ GCMemcardErrorCode Header::CheckForErrors(u16 card_size_mbits) const
|
||||
return error_code;
|
||||
}
|
||||
|
||||
bool Header::IsShiftJIS() const
|
||||
{
|
||||
return m_data.m_encoding != 0;
|
||||
}
|
||||
|
||||
Directory::Directory()
|
||||
{
|
||||
memset(reinterpret_cast<u8*>(this), 0xFF, BLOCK_SIZE);
|
||||
|
@ -231,6 +231,8 @@ struct Header
|
||||
std::pair<u16, u16> CalculateChecksums() const;
|
||||
|
||||
GCMemcardErrorCode CheckForErrors(u16 card_size_mbits) const;
|
||||
|
||||
bool IsShiftJIS() const;
|
||||
};
|
||||
static_assert(sizeof(Header) == BLOCK_SIZE);
|
||||
static_assert(std::is_trivially_copyable_v<Header>);
|
||||
@ -239,9 +241,6 @@ struct DEntry
|
||||
{
|
||||
DEntry();
|
||||
|
||||
// TODO: This probably shouldn't be here at all?
|
||||
std::string GCI_FileName() const;
|
||||
|
||||
static constexpr std::array<u8, 4> UNINITIALIZED_GAMECODE{{0xFF, 0xFF, 0xFF, 0xFF}};
|
||||
|
||||
// 4 bytes at 0x00: Gamecode
|
||||
|
@ -9,6 +9,7 @@
|
||||
#include <memory>
|
||||
#include <mutex>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#include <vector>
|
||||
|
||||
#include <fmt/format.h>
|
||||
@ -39,6 +40,28 @@
|
||||
|
||||
static const char* MC_HDR = "MC_SYSTEM_AREA";
|
||||
|
||||
static std::string GenerateDefaultGCIFilename(const Memcard::DEntry& entry,
|
||||
bool card_encoding_is_shift_jis)
|
||||
{
|
||||
const auto string_decoder = card_encoding_is_shift_jis ? SHIFTJISToUTF8 : CP1252ToUTF8;
|
||||
const auto strip_null = [](const std::string_view& s) {
|
||||
auto offset = s.find('\0');
|
||||
if (offset == std::string_view::npos)
|
||||
return s;
|
||||
return s.substr(0, offset);
|
||||
};
|
||||
|
||||
const std::string_view makercode(reinterpret_cast<const char*>(entry.m_makercode.data()),
|
||||
entry.m_makercode.size());
|
||||
const std::string_view gamecode(reinterpret_cast<const char*>(entry.m_gamecode.data()),
|
||||
entry.m_gamecode.size());
|
||||
const std::string_view filename(reinterpret_cast<const char*>(entry.m_filename.data()),
|
||||
entry.m_filename.size());
|
||||
return Common::EscapeFileName(fmt::format("{}-{}-{}.gci", strip_null(string_decoder(makercode)),
|
||||
strip_null(string_decoder(gamecode)),
|
||||
strip_null(string_decoder(filename))));
|
||||
}
|
||||
|
||||
bool GCMemcardDirectory::LoadGCI(Memcard::GCIFile gci)
|
||||
{
|
||||
// check if any already loaded file has the same internal name as the new file
|
||||
@ -102,7 +125,8 @@ bool GCMemcardDirectory::LoadGCI(Memcard::GCIFile gci)
|
||||
|
||||
// This is only used by NetPlay but it made sense to put it here to keep the relevant code together
|
||||
std::vector<std::string> GCMemcardDirectory::GetFileNamesForGameID(const std::string& directory,
|
||||
const std::string& game_id)
|
||||
const std::string& game_id,
|
||||
bool card_encoding_is_shift_jis)
|
||||
{
|
||||
std::vector<std::string> filenames;
|
||||
|
||||
@ -123,7 +147,8 @@ std::vector<std::string> GCMemcardDirectory::GetFileNamesForGameID(const std::st
|
||||
if (!gci_file.ReadBytes(&gci.m_gci_header, Memcard::DENTRY_SIZE))
|
||||
continue;
|
||||
|
||||
const std::string gci_filename = gci.m_gci_header.GCI_FileName();
|
||||
const std::string gci_filename =
|
||||
GenerateDefaultGCIFilename(gci.m_gci_header, card_encoding_is_shift_jis);
|
||||
if (std::find(loaded_saves.begin(), loaded_saves.end(), gci_filename) != loaded_saves.end())
|
||||
continue;
|
||||
|
||||
@ -614,7 +639,8 @@ void GCMemcardDirectory::FlushToFile()
|
||||
}
|
||||
if (save.m_filename.empty())
|
||||
{
|
||||
std::string default_save_name = m_save_directory + save.m_gci_header.GCI_FileName();
|
||||
std::string default_save_name =
|
||||
m_save_directory + GenerateDefaultGCIFilename(save.m_gci_header, m_hdr.IsShiftJIS());
|
||||
|
||||
// Check to see if another file is using the same name
|
||||
// This seems unlikely except in the case of file corruption
|
||||
|
@ -32,7 +32,8 @@ public:
|
||||
GCMemcardDirectory& operator=(GCMemcardDirectory&&) = delete;
|
||||
|
||||
static std::vector<std::string> GetFileNamesForGameID(const std::string& directory,
|
||||
const std::string& game_id);
|
||||
const std::string& game_id,
|
||||
bool card_encoding_is_shift_jis);
|
||||
void FlushToFile();
|
||||
void FlushThread();
|
||||
s32 Read(u32 src_address, s32 length, u8* dest_address) override;
|
||||
|
@ -1686,7 +1686,8 @@ bool NetPlayServer::SyncSaveData(const SaveSyncInfo& sync_info)
|
||||
return true;
|
||||
|
||||
const auto game_region = sync_info.game->GetRegion();
|
||||
const std::string region = Config::GetDirectoryForRegion(Config::ToGameCubeRegion(game_region));
|
||||
const auto gamecube_region = Config::ToGameCubeRegion(game_region);
|
||||
const std::string region = Config::GetDirectoryForRegion(gamecube_region);
|
||||
|
||||
for (ExpansionInterface::Slot slot : ExpansionInterface::MEMCARD_SLOTS)
|
||||
{
|
||||
@ -1733,8 +1734,8 @@ bool NetPlayServer::SyncSaveData(const SaveSyncInfo& sync_info)
|
||||
|
||||
if (File::IsDirectory(path))
|
||||
{
|
||||
std::vector<std::string> files =
|
||||
GCMemcardDirectory::GetFileNamesForGameID(path + DIR_SEP, sync_info.game->GetGameID());
|
||||
std::vector<std::string> files = GCMemcardDirectory::GetFileNamesForGameID(
|
||||
path + DIR_SEP, sync_info.game->GetGameID(), gamecube_region == DiscIO::Region::NTSC_J);
|
||||
|
||||
pac << static_cast<u8>(files.size());
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user