Skip to content

Commit

Permalink
Speed up getting a list of files on PS Vita (#9310)
Browse files Browse the repository at this point in the history
  • Loading branch information
oleg-derevenetz authored Dec 3, 2024
1 parent 2b4f5e3 commit 25d8607
Show file tree
Hide file tree
Showing 4 changed files with 90 additions and 14 deletions.
5 changes: 3 additions & 2 deletions Makefile.vita
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
###########################################################################
# fheroes2: https://github.com/ihhub/fheroes2 #
# Copyright (C) 2021 - 2023 #
# Copyright (C) 2021 - 2024 #
# #
# This program is free software; you can redistribute it and/or modify #
# it under the terms of the GNU General Public License as published by #
Expand Down Expand Up @@ -29,6 +29,7 @@ MAKE := make

PROJECT_TITLE := fheroes2
PROJECT_TITLEID := FHOMM0002
PROJECT_VERSION := $(file < version.txt)

.PHONY: all clean $(TARGET).vpk param.sfo $(TARGET).elf translations

Expand Down Expand Up @@ -56,7 +57,7 @@ eboot.bin: $(TARGET).velf
vita-make-fself $(TARGET).velf eboot.bin

param.sfo:
vita-mksfoex -s TITLE_ID="$(PROJECT_TITLEID)" "$(PROJECT_TITLE)" param.sfo
vita-mksfoex -s TITLE_ID="$(PROJECT_TITLEID)" -s APP_VER="$(PROJECT_VERSION)" "$(PROJECT_TITLE)" param.sfo

$(TARGET).velf: $(TARGET).elf
arm-vita-eabi-strip -g $<
Expand Down
87 changes: 81 additions & 6 deletions src/engine/dir.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,14 @@

#include "dir.h"

#include <utility>

#if defined( TARGET_PS_VITA )
#include <psp2/io/dirent.h>
#else
#include <filesystem>
#include <system_error>
#include <utility>
#endif

#if defined( _WIN32 )
#include <cstring>
Expand Down Expand Up @@ -57,7 +62,7 @@ namespace
return ( strCmp( filenamePtr, filter.c_str() ) == 0 );
}

void getFilesFromDirectory( const std::string_view path, const std::string & filter, const bool needExactMatch, ListFiles & files )
void getFilesFromDirectory( const std::string & path, const std::string & filter, const bool needExactMatch, ListFiles & files )
{
std::string correctedPath;
if ( !System::GetCaseInsensitivePath( path, correctedPath ) ) {
Expand All @@ -70,6 +75,62 @@ namespace
auto * const strCmp = strcasecmp;
#endif

#if defined( TARGET_PS_VITA )
// On PS Vita, getting a list of files using std::filesystem for some reason works much slower than using the native file system API
class SceUIDWrapper
{
public:
SceUIDWrapper( const std::string & path )
: uid( sceIoDopen( path.c_str() ) )
{}

SceUIDWrapper( const SceUIDWrapper & ) = delete;

~SceUIDWrapper()
{
if ( !isValid() ) {
return;
}

sceIoDclose( uid );
}

SceUIDWrapper & operator=( const SceUIDWrapper & ) = delete;

bool isValid() const
{
return uid >= 0;
}

SceUID get() const
{
return uid;
}

private:
const SceUID uid;
};

const SceUIDWrapper uid( path );
if ( !uid.isValid() ) {
return;
}

SceIoDirent entry;

while ( sceIoDread( uid.get(), &entry ) > 0 ) {
// Ensure that this directory entry is a regular file
if ( !SCE_S_ISREG( entry.d_stat.st_mode ) ) {
continue;
}

if ( !nameFilter( entry.d_name, needExactMatch, filter, strCmp ) ) {
continue;
}

files.emplace_back( System::concatPath( path, entry.d_name ) );
}
#else
std::error_code ec;

// Using the non-throwing overload
Expand All @@ -87,6 +148,7 @@ namespace

files.emplace_back( System::fsPathToString( entryPath ) );
}
#endif
}
}

Expand All @@ -97,17 +159,30 @@ void ListFiles::Append( ListFiles && files )
}
}

void ListFiles::ReadDir( const std::string_view path, const std::string & filter )
void ListFiles::ReadDir( const std::string & path, const std::string & filter )
{
getFilesFromDirectory( path, filter, false, *this );
}

void ListFiles::FindFileInDir( const std::string_view path, const std::string & fileName )
void ListFiles::FindFileInDir( const std::string_view path, const std::string_view fileName )
{
getFilesFromDirectory( path, fileName, true, *this );
std::string correctedFilePath;
// If the file system is case-sensitive, then here we will get the actual file path using the case-insensitive
// search (if such a file exists). If the file system is case-insensitive, we will just get the passed path to
// the file back intact.
if ( !System::GetCaseInsensitivePath( System::concatPath( path, fileName ), correctedFilePath ) ) {
return;
}

// In case the file system is case-insensitive, we additionally check the file for existence.
if ( !System::IsFile( correctedFilePath ) ) {
return;
}

emplace_back( std::move( correctedFilePath ) );
}

bool ListFiles::IsEmpty( const std::string_view path, const std::string & filter )
bool ListFiles::IsEmpty( const std::string & path, const std::string & filter )
{
ListFiles list;
list.ReadDir( path, filter );
Expand Down
8 changes: 4 additions & 4 deletions src/engine/dir.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,13 +32,13 @@ struct ListFiles : public std::list<std::string>
void Append( ListFiles && files );

// Adds files from the 'path' directory ending in 'filter' to the list, case-insensitive.
void ReadDir( const std::string_view path, const std::string & filter );
void ReadDir( const std::string & path, const std::string & filter );

// Adds files from the 'path' directory with names matching 'fileName' to the list, case-insensitive.
void FindFileInDir( const std::string_view path, const std::string & fileName );
// Adds the first found file from the 'path' directory with a name matching 'fileName' to the list, case-insensitive.
void FindFileInDir( const std::string_view path, const std::string_view fileName );

// Returns true if there are no files in the 'path' directory with names ending in 'filter', case-insensitive, otherwise returns false.
static bool IsEmpty( const std::string_view path, const std::string & filter );
static bool IsEmpty( const std::string & path, const std::string & filter );
};

#endif
4 changes: 2 additions & 2 deletions src/engine/system.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@
#include <algorithm>
#endif

#if !defined( _WIN32 ) && !defined( ANDROID )
#if !defined( _WIN32 ) && !defined( ANDROID ) && !defined( TARGET_PS_VITA )
#include <dirent.h>
#include <strings.h>
#endif
Expand Down Expand Up @@ -447,7 +447,7 @@ bool System::IsDirectory( const std::string_view path )

bool System::GetCaseInsensitivePath( const std::string_view path, std::string & correctedPath )
{
#if !defined( _WIN32 ) && !defined( ANDROID )
#if !defined( _WIN32 ) && !defined( ANDROID ) && !defined( TARGET_PS_VITA )
// The following code is based on https://github.com/OneSadCookie/fcaseopen and assumes the use of POSIX IEEE Std 1003.1-2001 pathnames
correctedPath.clear();

Expand Down

0 comments on commit 25d8607

Please sign in to comment.