diff --git a/src/core/memory_card_image.cpp b/src/core/memory_card_image.cpp index fdba23ca0..8630d63a3 100644 --- a/src/core/memory_card_image.cpp +++ b/src/core/memory_card_image.cpp @@ -3,6 +3,7 @@ #include "memory_card_image.h" #include "gpu_types.h" +#include "host.h" #include "system.h" #include "util/shiftjis.h" @@ -36,7 +37,7 @@ struct DirectoryFrame u32 block_allocation_state; u32 file_size; u16 next_block_number; - char filename[FILE_NAME_LENGTH + 1]; + char filename[FILE_TOTAL_LENGTH + 1]; u8 zero_pad_1; u8 pad_2[95]; u8 checksum; @@ -324,11 +325,12 @@ bool MemoryCardImage::ReadFile(const DataArray& data, const FileInfo& fi, std::v return true; } -bool MemoryCardImage::WriteFile(DataArray* data, std::string_view filename, const std::span buffer, Error* error) +bool MemoryCardImage::WriteFile(DataArray* data, std::string_view filename, const std::span buffer, + Error* error) { if (buffer.empty()) { - Error::SetStringView(error, "Buffer is empty."); + Error::SetStringView(error, TRANSLATE_SV("MemoryCard", "Buffer is empty.")); return false; } @@ -336,8 +338,9 @@ bool MemoryCardImage::WriteFile(DataArray* data, std::string_view filename, cons const u32 num_blocks = (static_cast(buffer.size()) + (BLOCK_SIZE - 1)) / BLOCK_SIZE; if (free_block_count < num_blocks) { - Error::SetStringFmt(error, "Insufficient free blocks, {} blocks are needed, but only have {}.", num_blocks, - free_block_count); + Error::SetStringFmt(error, + TRANSLATE_FS("MemoryCard", "Insufficient free blocks, {} blocks are needed, but only have {}."), + num_blocks, free_block_count); return false; } @@ -481,12 +484,41 @@ bool MemoryCardImage::UndeleteFile(DataArray* data, const FileInfo& fi) return true; } +bool MemoryCardImage::RenameFile(DataArray* data, const FileInfo& fi, std::string_view new_filename, Error* error) +{ + if (new_filename.length() > FILE_TOTAL_LENGTH) + { + Error::SetStringFmt(error, TRANSLATE_FS("MemoryCard", "File name must be at maximum {} characters long."), + static_cast(FILE_TOTAL_LENGTH)); + return false; + } + + for (const FileInfo& other_file : EnumerateFiles(*data, false)) + { + if (other_file.filename == new_filename) + { + Error::SetStringFmt( + error, TRANSLATE_FS("MemoryCard", "Save file with the same name '{}' already exists in memory card."), + new_filename); + return false; + } + } + + DirectoryFrame* df = GetFramePtr(data, 0, fi.first_block); + for (size_t i = 0; i < new_filename.length(); i++) + df->filename[i] = new_filename[i]; + for (size_t i = new_filename.length(); i < FILE_TOTAL_LENGTH; i++) + df->filename[i] = '\0'; + UpdateChecksum(df); + return true; +} + bool MemoryCardImage::ImportCardMCD(DataArray* data, const char* filename, std::span file_data, Error* error) { if (file_data.size() != DATA_SIZE) { - Error::SetStringFmt(error, "File is incorrect size, expected {} bytes, got {} bytes.", static_cast(DATA_SIZE), - file_data.size()); + Error::SetStringFmt(error, TRANSLATE_FS("MemoryCard", "File is incorrect size, expected {} bytes, got {} bytes."), + static_cast(DATA_SIZE), file_data.size()); return false; } @@ -518,8 +550,9 @@ bool MemoryCardImage::ImportCardGME(DataArray* data, const char* filename, std:: if (file_data.size() < MIN_SIZE) { - Error::SetStringFmt(error, "File is incorrect size, expected at least {} bytes, got {} bytes.", MIN_SIZE, - file_data.size()); + Error::SetStringFmt(error, + TRANSLATE_FS("MemoryCard", "File is incorrect size, expected at least {} bytes, got {} bytes."), + MIN_SIZE, file_data.size()); return false; } @@ -556,15 +589,15 @@ bool MemoryCardImage::ImportCardVGS(DataArray* data, const char* filename, std:: if (file_data.size() != EXPECTED_SIZE) { - Error::SetStringFmt(error, "File is incorrect size, expected {} bytes, got {} bytes.", EXPECTED_SIZE, - file_data.size()); + Error::SetStringFmt(error, TRANSLATE_FS("MemoryCard", "File is incorrect size, expected {} bytes, got {} bytes."), + EXPECTED_SIZE, file_data.size()); return false; } // Connectix Virtual Game Station format (.MEM): "VgsM", 64 bytes if (file_data[0] != 'V' || file_data[1] != 'g' || file_data[2] != 's' || file_data[3] != 'M') { - Error::SetStringView(error, "Incorrect header."); + Error::SetStringView(error, TRANSLATE_SV("MemoryCard", "Incorrect header.")); return false; } @@ -579,15 +612,15 @@ bool MemoryCardImage::ImportCardPSX(DataArray* data, const char* filename, std:: if (file_data.size() != EXPECTED_SIZE) { - Error::SetStringFmt(error, "File is incorrect size, expected {} bytes, got {} bytes.", EXPECTED_SIZE, - file_data.size()); + Error::SetStringFmt(error, TRANSLATE_FS("MemoryCard", "File is incorrect size, expected {} bytes, got {} bytes."), + EXPECTED_SIZE, file_data.size()); return false; } // Connectix Virtual Game Station format (.MEM): "VgsM", 64 bytes if (file_data[0] != 'P' || file_data[1] != 'S' || file_data[2] != 'V') { - Error::SetStringView(error, "Incorrect header."); + Error::SetStringView(error, TRANSLATE_SV("MemoryCard", "Incorrect header.")); return false; } @@ -600,7 +633,7 @@ bool MemoryCardImage::ImportCard(DataArray* data, const char* filename, std::spa const std::string_view extension = Path::GetExtension(filename); if (extension.empty()) { - Error::SetStringFmt(error, "File must have an extension."); + Error::SetStringView(error, TRANSLATE_SV("MemoryCard", "File must have an extension.")); return false; } @@ -625,7 +658,7 @@ bool MemoryCardImage::ImportCard(DataArray* data, const char* filename, std::spa } else { - Error::SetStringFmt(error, "Unknown extension '{}'.", extension); + Error::SetStringFmt(error, TRANSLATE_FS("MemoryCard", "Unknown extension '{}'."), extension); return false; } } @@ -668,7 +701,7 @@ bool MemoryCardImage::ImportSaveWithDirectoryFrame(DataArray* data, const char* // 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) { - Error::SetStringView(error, "Invalid size for save file."); + Error::SetStringView(error, TRANSLATE_SV("MemoryCard", "Invalid size for save file.")); return false; } @@ -679,28 +712,29 @@ bool MemoryCardImage::ImportSaveWithDirectoryFrame(DataArray* data, const char* DirectoryFrame df; if (std::fread(&df, sizeof(df), 1, fp.get()) != 1) { - Error::SetErrno(error, "Failed to read directory frame: ", errno); + Error::SetErrno(error, TRANSLATE_SV("MemoryCard", "Failed to read directory frame: "), errno); return false; } // Make sure the size reported by the directory frame is valid if (df.file_size < BLOCK_SIZE || df.file_size % BLOCK_SIZE != 0 || df.file_size / BLOCK_SIZE > 15u) { - Error::SetStringFmt(error, "Invalid size ({} bytes) reported by directory frame.", df.file_size); + Error::SetStringFmt(error, TRANSLATE_FS("MemoryCard", "Invalid size ({} bytes) reported by directory frame."), + df.file_size); return false; } std::vector blocks = std::vector(static_cast(df.file_size)); if (std::fread(blocks.data(), df.file_size, 1, fp.get()) != 1) { - Error::SetErrno(error, "Failed to read block bytes: ", errno); + Error::SetErrno(error, TRANSLATE_SV("MemoryCard", "Failed to read block bytes: "), errno); return false; } const u32 num_blocks = (static_cast(blocks.size()) + (BLOCK_SIZE - 1)) / BLOCK_SIZE; if (GetFreeBlockCount(*data) < num_blocks) { - Error::SetStringView(error, "Insufficient free blocks."); + Error::SetStringView(error, TRANSLATE_SV("MemoryCard", "Insufficient free blocks.")); return false; } @@ -712,7 +746,9 @@ bool MemoryCardImage::ImportSaveWithDirectoryFrame(DataArray* data, const char* { if (!fi.deleted) { - Error::SetStringFmt(error, "Save file with the same name '{}' already exists in memory card", fi.filename); + Error::SetStringFmt( + error, TRANSLATE_FS("MemoryCard", "Save file with the same name '{}' already exists in memory card."), + fi.filename); return false; } @@ -729,7 +765,7 @@ bool MemoryCardImage::ImportRawSave(DataArray* data, const char* filename, const std::string save_name(Path::GetFileTitle(filename)); if (save_name.length() == 0) { - Error::SetStringView(error, "Invalid filename."); + Error::SetStringView(error, TRANSLATE_SV("MemoryCard", "Invalid filename.")); return false; } @@ -744,8 +780,9 @@ bool MemoryCardImage::ImportRawSave(DataArray* data, const char* filename, const const u32 num_blocks = (static_cast(blocks->size()) + (BLOCK_SIZE - 1)) / BLOCK_SIZE; if (free_block_count < num_blocks) { - Error::SetStringFmt(error, "Insufficient free blocks, needs {} blocks, but only have {}.", num_blocks, - free_block_count); + Error::SetStringFmt(error, + TRANSLATE_FS("MemoryCard", "Insufficient free blocks, needs {} blocks, but only have {}."), + num_blocks, free_block_count); return false; } @@ -757,7 +794,9 @@ bool MemoryCardImage::ImportRawSave(DataArray* data, const char* filename, const { if (!fi.deleted) { - Error::SetStringFmt(error, "Save file with the same name '{}' already exists in memory card.", fi.filename); + Error::SetStringFmt( + error, TRANSLATE_FS("MemoryCard", "Save file with the same name '{}' already exists in memory card."), + fi.filename); return false; } @@ -774,7 +813,7 @@ bool MemoryCardImage::ImportSave(DataArray* data, const char* filename, Error* e FILESYSTEM_STAT_DATA sd; if (!FileSystem::StatFile(filename, &sd) || sd.Size == 0) { - Error::SetStringView(error, "File does not exist, or is empty."); + Error::SetStringView(error, TRANSLATE_SV("MemoryCard", "File does not exist, or is empty.")); return false; } @@ -788,7 +827,7 @@ bool MemoryCardImage::ImportSave(DataArray* data, const char* filename, Error* e } else { - Error::SetStringView(error, "Unknown save format."); + Error::SetStringView(error, TRANSLATE_SV("MemoryCard", "Unknown save format.")); return false; } } diff --git a/src/core/memory_card_image.h b/src/core/memory_card_image.h index e9d014eb4..f50638f89 100644 --- a/src/core/memory_card_image.h +++ b/src/core/memory_card_image.h @@ -21,7 +21,12 @@ enum : u32 NUM_BLOCKS = DATA_SIZE / BLOCK_SIZE, NUM_FRAMES = DATA_SIZE / FRAME_SIZE, ICON_WIDTH = 16, - ICON_HEIGHT = 16 + ICON_HEIGHT = 16, + + FILE_REGION_LENGTH = 2, + FILE_SERIAL_LENGTH = 10, + FILE_FILENAME_LENGTH = 8, + FILE_TOTAL_LENGTH = FILE_REGION_LENGTH + FILE_SERIAL_LENGTH + FILE_FILENAME_LENGTH, }; using DataArray = std::array; @@ -55,6 +60,7 @@ bool ReadFile(const DataArray& data, const FileInfo& fi, std::vector* buffer bool WriteFile(DataArray* data, std::string_view filename, std::span buffer, Error* error); bool DeleteFile(DataArray* data, const FileInfo& fi, bool clear_sectors); bool UndeleteFile(DataArray* data, const FileInfo& fi); +bool RenameFile(DataArray* data, const FileInfo& fi, std::string_view new_filename, Error* error); bool ImportCard(DataArray* data, const char* filename, Error* error); bool ImportCard(DataArray* data, const char* filename, std::span file_data, Error* error); bool ExportSave(DataArray* data, const FileInfo& fi, const char* filename, Error* error);