mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2025-01-10 08:09:26 +01:00
GCMemcard: Read file comments according to logical data offsets instead of physical data offsets.
This commit is contained in:
parent
770605bc80
commit
58f21830bd
@ -639,43 +639,33 @@ std::optional<std::vector<u8>> GCMemcard::GetSaveDataBytes(u8 save_index, size_t
|
||||
return std::make_optional(std::move(result));
|
||||
}
|
||||
|
||||
u32 GCMemcard::DEntry_CommentsAddress(u8 index) const
|
||||
std::optional<std::pair<std::string, std::string>> GCMemcard::GetSaveComments(u8 index) const
|
||||
{
|
||||
if (!m_valid || index >= DIRLEN)
|
||||
return 0xFFFF;
|
||||
return std::nullopt;
|
||||
|
||||
return GetActiveDirectory().m_dir_entries[index].m_comments_address;
|
||||
}
|
||||
const u32 address = GetActiveDirectory().m_dir_entries[index].m_comments_address;
|
||||
if (address == 0xFFFFFFFF)
|
||||
return std::nullopt;
|
||||
|
||||
std::string GCMemcard::GetSaveComment1(u8 index) const
|
||||
{
|
||||
if (!m_valid || index >= DIRLEN)
|
||||
return "";
|
||||
const auto data = GetSaveDataBytes(index, address, DENTRY_STRLEN * 2);
|
||||
if (!data || data->size() != DENTRY_STRLEN * 2)
|
||||
return std::nullopt;
|
||||
|
||||
u32 Comment1 = GetActiveDirectory().m_dir_entries[index].m_comments_address;
|
||||
u32 DataBlock = GetActiveDirectory().m_dir_entries[index].m_first_block - MC_FST_BLOCKS;
|
||||
if ((DataBlock > m_size_blocks) || (Comment1 == 0xFFFFFFFF))
|
||||
{
|
||||
return "";
|
||||
}
|
||||
return std::string((const char*)m_data_blocks[DataBlock].m_block.data() + Comment1,
|
||||
DENTRY_STRLEN);
|
||||
}
|
||||
const auto string_decoder = IsShiftJIS() ? SHIFTJISToUTF8 : CP1252ToUTF8;
|
||||
const auto strip_null = [](const std::string& s) {
|
||||
auto offset = s.find('\0');
|
||||
if (offset == std::string::npos)
|
||||
offset = s.length();
|
||||
return s.substr(0, offset);
|
||||
};
|
||||
|
||||
std::string GCMemcard::GetSaveComment2(u8 index) const
|
||||
{
|
||||
if (!m_valid || index >= DIRLEN)
|
||||
return "";
|
||||
|
||||
u32 Comment1 = GetActiveDirectory().m_dir_entries[index].m_comments_address;
|
||||
u32 Comment2 = Comment1 + DENTRY_STRLEN;
|
||||
u32 DataBlock = GetActiveDirectory().m_dir_entries[index].m_first_block - MC_FST_BLOCKS;
|
||||
if ((DataBlock > m_size_blocks) || (Comment1 == 0xFFFFFFFF))
|
||||
{
|
||||
return "";
|
||||
}
|
||||
return std::string((const char*)m_data_blocks[DataBlock].m_block.data() + Comment2,
|
||||
DENTRY_STRLEN);
|
||||
const u8* address_1 = data->data();
|
||||
const u8* address_2 = address_1 + DENTRY_STRLEN;
|
||||
const std::string encoded_1(reinterpret_cast<const char*>(address_1), DENTRY_STRLEN);
|
||||
const std::string encoded_2(reinterpret_cast<const char*>(address_2), DENTRY_STRLEN);
|
||||
return std::make_pair(strip_null(string_decoder(encoded_1)),
|
||||
strip_null(string_decoder(encoded_2)));
|
||||
}
|
||||
|
||||
std::optional<DEntry> GCMemcard::GetDEntry(u8 index) const
|
||||
|
@ -118,7 +118,7 @@ constexpr u32 MC_FST_BLOCKS = 0x05;
|
||||
// maximum number of saves that can be stored on a single memory card
|
||||
constexpr u8 DIRLEN = 0x7F;
|
||||
|
||||
// maximum size of memory card file comment in bytes
|
||||
// maximum size of a single memory card file comment in bytes
|
||||
constexpr u32 DENTRY_STRLEN = 0x20;
|
||||
|
||||
// size of a single entry in the Directory in bytes
|
||||
@ -456,9 +456,10 @@ public:
|
||||
GetSaveDataBytes(u8 save_index, size_t offset = 0,
|
||||
size_t length = std::numeric_limits<size_t>::max()) const;
|
||||
|
||||
u32 DEntry_CommentsAddress(u8 index) const;
|
||||
std::string GetSaveComment1(u8 index) const;
|
||||
std::string GetSaveComment2(u8 index) const;
|
||||
// Returns, if available, the two strings shown on the save file in the GC BIOS, in UTF8.
|
||||
// The first is the big line on top, usually the game title, and the second is the smaller line
|
||||
// next to the block size, often a progress indicator or subtitle.
|
||||
std::optional<std::pair<std::string, std::string>> GetSaveComments(u8 index) const;
|
||||
|
||||
// Fetches a DEntry from the given file index.
|
||||
std::optional<DEntry> GetDEntry(u8 index) const;
|
||||
|
@ -186,14 +186,6 @@ void GCMemcardManager::UpdateSlotTable(int slot)
|
||||
return item;
|
||||
};
|
||||
|
||||
const auto strip_garbage = [](const std::string& s) {
|
||||
auto offset = s.find('\0');
|
||||
if (offset == std::string::npos)
|
||||
offset = s.length();
|
||||
|
||||
return s.substr(0, offset);
|
||||
};
|
||||
|
||||
const u8 num_files = memcard->GetNumFiles();
|
||||
m_slot_active_icons[slot].reserve(num_files);
|
||||
for (int i = 0; i < num_files; i++)
|
||||
@ -201,12 +193,16 @@ void GCMemcardManager::UpdateSlotTable(int slot)
|
||||
int file_index = memcard->GetFileIndex(i);
|
||||
table->setRowCount(i + 1);
|
||||
|
||||
auto const string_decoder = memcard->IsShiftJIS() ? SHIFTJISToUTF8 : CP1252ToUTF8;
|
||||
const auto file_comments = memcard->GetSaveComments(file_index);
|
||||
|
||||
QString title;
|
||||
QString comment;
|
||||
if (file_comments)
|
||||
{
|
||||
title = QString::fromStdString(file_comments->first);
|
||||
comment = QString::fromStdString(file_comments->second);
|
||||
}
|
||||
|
||||
QString title =
|
||||
QString::fromStdString(strip_garbage(string_decoder(memcard->GetSaveComment1(file_index))));
|
||||
QString comment =
|
||||
QString::fromStdString(strip_garbage(string_decoder(memcard->GetSaveComment2(file_index))));
|
||||
QString blocks = QStringLiteral("%1").arg(memcard->DEntry_BlockCount(file_index));
|
||||
QString block_count = QStringLiteral("%1").arg(memcard->DEntry_FirstBlock(file_index));
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user