From ed6145ac773e823f9342e84feb8e47c06a9d1e5d Mon Sep 17 00:00:00 2001 From: Connor McLaughlin Date: Mon, 21 Jun 2021 17:24:51 +1000 Subject: [PATCH] Qt/MemoryCardEditor: Support importing non-mcs raw files --- src/core/memory_card_image.cpp | 80 ++++++++++++++++--- src/duckstation-qt/memorycardeditordialog.cpp | 3 +- 2 files changed, 73 insertions(+), 10 deletions(-) diff --git a/src/core/memory_card_image.cpp b/src/core/memory_card_image.cpp index 562b9286b..3287fc1ef 100644 --- a/src/core/memory_card_image.cpp +++ b/src/core/memory_card_image.cpp @@ -18,10 +18,15 @@ namespace MemoryCardImage { struct DirectoryFrame { + enum : u32 + { + FILE_NAME_LENGTH = 20 + }; + u32 block_allocation_state; u32 file_size; u16 next_block_number; - char filename[21]; + char filename[FILE_NAME_LENGTH + 1]; u8 zero_pad_1; u8 pad_2[95]; u8 checksum; @@ -507,15 +512,8 @@ bool ExportSave(DataArray* data, const FileInfo& fi, const char* filename) return true; } -bool ImportSave(DataArray* data, const char* filename) +static bool ImportSaveWithDirectoryFrame(DataArray* data, const char* filename, const FILESYSTEM_STAT_DATA& sd) { - FILESYSTEM_STAT_DATA sd; - if (!FileSystem::StatFile(filename, &sd)) - { - Log_ErrorPrintf("Failed to stat file '%s'", filename); - return false; - } - // Make sure the size of the actual file is valid if (sd.Size <= FRAME_SIZE || (sd.Size - FRAME_SIZE) % BLOCK_SIZE != 0u || (sd.Size - FRAME_SIZE) / BLOCK_SIZE > 15u) { @@ -565,4 +563,68 @@ bool ImportSave(DataArray* data, const char* filename) return WriteFile(data, df.filename, blocks); } +static bool ImportRawSave(DataArray* data, const char* filename, const FILESYSTEM_STAT_DATA& sd) +{ + std::string save_name(FileSystem::GetFileTitleFromPath(filename)); + if (save_name.length() == 0) + { + Log_ErrorPrintf("Invalid filename: '%s'", filename); + return false; + } + + if (save_name.length() > DirectoryFrame::FILE_NAME_LENGTH) + save_name.erase(DirectoryFrame::FILE_NAME_LENGTH); + + // Make sure there isn't already a save with the same name + std::vector fileinfos = EnumerateFiles(*data); + for (const FileInfo& fi : fileinfos) + { + if (fi.filename.compare(save_name) == 0) + { + Log_ErrorPrintf("Save file with the same name (%s) already exists in memory card", save_name.c_str()); + return false; + } + } + + std::optional> blocks = FileSystem::ReadBinaryFile(filename); + if (!blocks.has_value()) + { + Log_ErrorPrintf("Failed to read '%s'", filename); + return false; + } + + return WriteFile(data, save_name, blocks.value()); +} + +bool ImportSave(DataArray* data, const char* filename) +{ + FILESYSTEM_STAT_DATA sd; + if (!FileSystem::StatFile(filename, &sd)) + { + Log_ErrorPrintf("Failed to stat file '%s'", filename); + return false; + } + + // Make sure the size of the actual file is valid + if (sd.Size == 0) + { + Log_ErrorPrintf("Invalid size for save file '%s'", filename); + return false; + } + + if (StringUtil::EndsWith(filename, ".mcs")) + { + return ImportSaveWithDirectoryFrame(data, filename, sd); + } + else if (sd.Size > 0 && sd.Size < DATA_SIZE && (sd.Size % BLOCK_SIZE) == 0) + { + return ImportRawSave(data, filename, sd); + } + else + { + Log_ErrorPrintf("Unknown save format for '%s'", filename); + return false; + } +} + } // namespace MemoryCardImage diff --git a/src/duckstation-qt/memorycardeditordialog.cpp b/src/duckstation-qt/memorycardeditordialog.cpp index 132131845..72fc1f61f 100644 --- a/src/duckstation-qt/memorycardeditordialog.cpp +++ b/src/duckstation-qt/memorycardeditordialog.cpp @@ -11,7 +11,8 @@ static constexpr char MEMORY_CARD_IMAGE_FILTER[] = QT_TRANSLATE_NOOP("MemoryCardEditorDialog", "All Memory Card Types (*.mcd *.mcr *.mc)"); static constexpr char MEMORY_CARD_IMPORT_FILTER[] = QT_TRANSLATE_NOOP("MemoryCardEditorDialog", "All Importable Memory Card Types (*.mcd *.mcr *.mc *.gme)"); -static constexpr char SINGLE_SAVEFILE_FILTER[] = TRANSLATABLE("MemoryCardEditorDialog", "Single Save Files (*.mcs)"); +static constexpr char SINGLE_SAVEFILE_FILTER[] = + TRANSLATABLE("MemoryCardEditorDialog", "Single Save Files (*.mcs);;All Files (*.*)"); MemoryCardEditorDialog::MemoryCardEditorDialog(QWidget* parent) : QDialog(parent) {