From 094684f0b999740205fcdb2287b2b6e7af28af47 Mon Sep 17 00:00:00 2001 From: Emmanuel Gil Peyrot Date: Mon, 29 Sep 2014 08:34:37 +0000 Subject: [PATCH] Common: Add a helper function to generate a 8.3 filename from a long one. Core: Fix the SDMC Directory implementation to make blargSnes work. --- src/common/file_util.cpp | 38 ++++++++++++++++++++++++++++ src/common/file_util.h | 3 +++ src/core/file_sys/directory_sdmc.cpp | 20 +++++---------- src/core/file_sys/directory_sdmc.h | 2 +- 4 files changed, 49 insertions(+), 14 deletions(-) diff --git a/src/common/file_util.cpp b/src/common/file_util.cpp index 40cd32d96..24cbd8f85 100644 --- a/src/common/file_util.cpp +++ b/src/common/file_util.cpp @@ -780,6 +780,44 @@ bool ReadFileToString(bool text_file, const char *filename, std::string &str) return file.ReadArray(&str[0], str.size()); } +// Splits the filename into 8.3 format +// Implemented following http://support2.microsoft.com/kb/142982 +void SplitFilename83(const std::string& filename, char *short_name, char *extension) +{ + int j = 0; + const std::string forbidden_characters = ".\"/\\[]:;=, "; + + memset(short_name, ' ', 8); + memset(extension, ' ', 3); + short_name[8] = '\0'; + extension[3] = '\0'; + + std::string::size_type point = filename.rfind('.'); + if (point == filename.size() - 1) + point = filename.rfind('.', point); + + // Get short name. + for (char letter: filename.substr(0, point)) { + if (-1 != forbidden_characters.find(letter, 0)) + continue; + if (j == 8) { + // TODO(Link Mauve): also do that for filenames containing a space. + // TODO(Link Mauve): handle multiple files having the same short name. + short_name[6] = '~'; + short_name[7] = '1'; + break; + } + short_name[j++] = toupper(letter); + } + + // Get extension. + if (point != std::string::npos) { + j = 0; + for (char letter: filename.substr(point + 1, 3)) + extension[j++] = toupper(letter); + } +} + IOFile::IOFile() : m_file(NULL), m_good(true) {} diff --git a/src/common/file_util.h b/src/common/file_util.h index cddcd1951..91c2600fd 100644 --- a/src/common/file_util.h +++ b/src/common/file_util.h @@ -131,6 +131,9 @@ std::string &GetExeDirectory(); bool WriteStringToFile(bool text_file, const std::string &str, const char *filename); bool ReadFileToString(bool text_file, const char *filename, std::string &str); +// Splits the filename into 8.3 format +void SplitFilename83(const std::string& filename, char *short_name, char *extension); + // simple wrapper for cstdlib file functions to // hopefully will make error checking easier // and make forgetting an fclose() harder diff --git a/src/core/file_sys/directory_sdmc.cpp b/src/core/file_sys/directory_sdmc.cpp index 11e867857..31a09b9ba 100644 --- a/src/core/file_sys/directory_sdmc.cpp +++ b/src/core/file_sys/directory_sdmc.cpp @@ -20,7 +20,8 @@ Directory_SDMC::Directory_SDMC(const Archive_SDMC* archive, const std::string& p // the root directory we set while opening the archive. // For example, opening /../../usr/bin can give the emulated program your installed programs. std::string absolute_path = archive->GetMountPoint() + path; - entry_count = FileUtil::ScanDirectoryTree(absolute_path, entry); + FileUtil::ScanDirectoryTree(absolute_path, directory); + entry_count = directory.children.size(); current_entry = 0; } @@ -37,8 +38,8 @@ Directory_SDMC::~Directory_SDMC() { u32 Directory_SDMC::Read(const u32 count, Entry* entries) { u32 i; for (i = 0; i < count && current_entry < entry_count; ++i) { - FileUtil::FSTEntry file = entry.children[current_entry]; - std::string filename = file.virtualName; + FileUtil::FSTEntry& file = directory.children[current_entry]; + std::string& filename = file.virtualName; WARN_LOG(FILESYS, "File %s: size=%d dir=%d", filename.c_str(), file.size, file.isDirectory); Entry* entry = &entries[i]; @@ -50,18 +51,11 @@ u32 Directory_SDMC::Read(const u32 count, Entry* entries) { break; } - // Split the filename into 8.3 format. - // TODO(Link Mauve): move that to common, I guess, and make it more robust to long filenames. - std::string::size_type n = filename.rfind('.'); - if (n == std::string::npos) { - strncpy(entry->short_name, filename.c_str(), 8); - memset(entry->extension, '\0', 3); - } else { - strncpy(entry->short_name, filename.substr(0, n).c_str(), 8); - strncpy(entry->extension, filename.substr(n + 1).c_str(), 8); - } + FileUtil::SplitFilename83(filename, entry->short_name, entry->extension); entry->is_directory = file.isDirectory; + entry->is_hidden = filename[0] == '.'; + entry->is_read_only = 0; entry->file_size = file.size; // We emulate a SD card where the archive bit has never been cleared, as it would be on diff --git a/src/core/file_sys/directory_sdmc.h b/src/core/file_sys/directory_sdmc.h index 0bc6c9eff..c6e9d212f 100644 --- a/src/core/file_sys/directory_sdmc.h +++ b/src/core/file_sys/directory_sdmc.h @@ -39,7 +39,7 @@ public: private: u32 entry_count; u32 current_entry; - FileUtil::FSTEntry entry; + FileUtil::FSTEntry directory; }; } // namespace FileSys