FileSystem: Add a case-insensitive match for nvm and mec file loading.

This commit is contained in:
Ty Lamontagne 2024-11-29 11:57:39 -05:00 committed by Ty
parent e8dbcc31aa
commit a60489b6fd
4 changed files with 51 additions and 6 deletions

View File

@ -994,6 +994,37 @@ std::FILE* FileSystem::OpenCFile(const char* filename, const char* mode, Error*
#endif
}
std::FILE* FileSystem::OpenCFileTryIgnoreCase(const char* filename, const char* mode, Error* error)
{
#if defined(_WIN32) || defined(__APPLE__)
return OpenCFile(filename, mode, error);
#else
std::FILE* fp = std::fopen(filename, mode);
const auto cur_errno = errno;
if (!fp)
{
const auto dir = std::string(Path::GetDirectory(filename));
FindResultsArray files;
if (FindFiles(dir.c_str(), "*", FILESYSTEM_FIND_FILES | FILESYSTEM_FIND_HIDDEN_FILES, &files))
{
for (auto& file : files)
{
if (StringUtil::compareNoCase(file.FileName, filename))
{
fp = std::fopen(file.FileName.c_str(), mode);
break;
}
}
}
}
if (!fp)
Error::SetErrno(error, cur_errno);
return fp;
#endif
}
int FileSystem::OpenFDFile(const char* filename, int flags, int mode, Error* error)
{
#ifdef _WIN32
@ -1015,6 +1046,11 @@ FileSystem::ManagedCFilePtr FileSystem::OpenManagedCFile(const char* filename, c
return ManagedCFilePtr(OpenCFile(filename, mode, error));
}
FileSystem::ManagedCFilePtr FileSystem::OpenManagedCFileTryIgnoreCase(const char* filename, const char* mode, Error* error)
{
return ManagedCFilePtr(OpenCFileTryIgnoreCase(filename, mode, error));
}
std::FILE* FileSystem::OpenSharedCFile(const char* filename, const char* mode, FileShareMode share_mode, Error* error)
{
#ifdef _WIN32

View File

@ -106,7 +106,16 @@ namespace FileSystem
/// open files
using ManagedCFilePtr = std::unique_ptr<std::FILE, FileDeleter>;
ManagedCFilePtr OpenManagedCFile(const char* filename, const char* mode, Error* error = nullptr);
// Tries to open a file using the given filename, but if that fails searches
// the directory for a file with a case-insensitive match.
// This is the same as OpenManagedCFile on Windows and MacOS
ManagedCFilePtr OpenManagedCFileTryIgnoreCase(const char* filename, const char* mode, Error* error = nullptr);
std::FILE* OpenCFile(const char* filename, const char* mode, Error* error = nullptr);
// Tries to open a file using the given filename, but if that fails searches
// the directory for a file with a case-insensitive match.
// This is the same as OpenCFile on Windows and MacOS
std::FILE* OpenCFileTryIgnoreCase(const char* filename, const char* mode, Error* error = nullptr);
int FSeek64(std::FILE* fp, s64 offset, int whence);
s64 FTell64(std::FILE* fp);
s64 FSize64(std::FILE* fp);

View File

@ -155,7 +155,7 @@ void cdvdLoadNVRAM()
{
Error error;
const std::string nvmfile = cdvdGetNVRAMPath();
auto fp = FileSystem::OpenManagedCFile(nvmfile.c_str(), "rb", &error);
auto fp = FileSystem::OpenManagedCFileTryIgnoreCase(nvmfile.c_str(), "rb", &error);
if (!fp || std::fread(s_nvram, sizeof(s_nvram), 1, fp.get()) != 1)
{
ERROR_LOG("Failed to open or read NVRAM at {}: {}", Path::GetFileName(nvmfile), error.GetDescription());
@ -178,7 +178,7 @@ void cdvdLoadNVRAM()
// Also load the mechacon version while we're here.
const std::string mecfile = Path::ReplaceExtension(BiosPath, "mec");
fp = FileSystem::OpenManagedCFile(mecfile.c_str(), "rb", &error);
fp = FileSystem::OpenManagedCFileTryIgnoreCase(mecfile.c_str(), "rb", &error);
if (!fp || std::fread(&s_mecha_version, sizeof(s_mecha_version), 1, fp.get()) != 1)
{
s_mecha_version = DEFAULT_MECHA_VERSION;
@ -186,7 +186,7 @@ void cdvdLoadNVRAM()
ERROR_LOG("Failed to open or read MEC file at {}: {}, creating default.", Path::GetFileName(nvmfile),
error.GetDescription());
fp.reset();
fp = FileSystem::OpenManagedCFile(mecfile.c_str(), "wb");
fp = FileSystem::OpenManagedCFileTryIgnoreCase(mecfile.c_str(), "wb");
if (!fp || std::fwrite(&s_mecha_version, sizeof(s_mecha_version), 1, fp.get()) != 1)
Host::ReportErrorAsync("Error", "Failed to write MEC file. Check your BIOS setup/permission settings.");
}
@ -197,10 +197,10 @@ void cdvdSaveNVRAM()
{
Error error;
const std::string nvmfile = cdvdGetNVRAMPath();
auto fp = FileSystem::OpenManagedCFile(nvmfile.c_str(), "r+b", &error);
auto fp = FileSystem::OpenManagedCFileTryIgnoreCase(nvmfile.c_str(), "r+b", &error);
if (!fp)
{
fp = FileSystem::OpenManagedCFile(nvmfile.c_str(), "w+b", &error);
fp = FileSystem::OpenManagedCFileTryIgnoreCase(nvmfile.c_str(), "w+b", &error);
if (!fp) [[unlikely]]
{
ERROR_LOG("Failed to open NVRAM at {} for updating: {}", Path::GetFileName(nvmfile), error.GetDescription());

View File

@ -226,7 +226,7 @@ static void LoadExtraRom(const char* ext, u32 offset, u32 size)
BiosRom.resize(offset + size);
auto fp = FileSystem::OpenManagedCFile(Bios1.c_str(), "rb");
auto fp = FileSystem::OpenManagedCFileTryIgnoreCase(Bios1.c_str(), "rb");
if (!fp || std::fread(&BiosRom[offset], static_cast<size_t>(std::min<s64>(size, filesize)), 1, fp.get()) != 1)
{
Console.Warning("BIOS Warning: %s could not be read (permission denied?)", ext);