From 5f0c5d10998ab8d22737d84dc24b9906c4bf43bf Mon Sep 17 00:00:00 2001 From: Ghabry <gabriel+github@mastergk.de> Date: Mon, 1 Apr 2024 15:06:20 +0200 Subject: [PATCH 1/5] Game Browser: Support going up from the startup directory --- src/filefinder.cpp | 2 +- src/filesystem.cpp | 14 ++++++++++++++ src/filesystem.h | 13 +++++++++++++ src/main_data.cpp | 28 ++++++++++++++++++---------- src/scene_gamebrowser.cpp | 18 ++++++++++++------ src/window_gamelist.cpp | 8 +++++++- tests/filefinder.cpp | 4 ---- tests/output.cpp | 1 - 8 files changed, 65 insertions(+), 23 deletions(-) diff --git a/src/filefinder.cpp b/src/filefinder.cpp index cc6b9004cc..bc08b96770 100644 --- a/src/filefinder.cpp +++ b/src/filefinder.cpp @@ -143,7 +143,7 @@ FilesystemView FileFinder::Root() { root_fs = std::make_unique<RootFilesystem>(); } - return root_fs->Subtree(""); + return *root_fs; } std::string FileFinder::MakePath(StringView dir, StringView name) { diff --git a/src/filesystem.cpp b/src/filesystem.cpp index 132558f60c..a6757392a6 100644 --- a/src/filesystem.cpp +++ b/src/filesystem.cpp @@ -382,6 +382,20 @@ FilesystemView FilesystemView::Subtree(StringView sub_path) const { return FilesystemView(fs, MakePath(sub_path)); } +bool FilesystemView::CanGoUp() const { + return static_cast<bool>(GoUp()); +} + +FilesystemView FilesystemView::GoUp() const { + if (GetSubPath().empty() || GetSubPath() == "/") { + return fs->GetParent(); + } + + auto [path, file] = FileFinder::GetPathAndFilename(GetSubPath()); + + return FilesystemView(fs, path); +} + std::string FilesystemView::Describe() const { assert(fs); if (GetSubPath().empty()) { diff --git a/src/filesystem.h b/src/filesystem.h index 02936dcdee..736d476016 100644 --- a/src/filesystem.h +++ b/src/filesystem.h @@ -475,6 +475,19 @@ class FilesystemView { */ FilesystemView Subtree(StringView sub_path) const; + /** + * @return Whether it is possible to go up from the current view + */ + bool CanGoUp() const; + + /** + * From the current view goes up by one. + * Returns an invalid view when going up is not possible (no parent). + * + * @return View that is rooted at the parent. + */ + FilesystemView GoUp() const; + /** @return human readable representation of this filesystem for debug purposes */ std::string Describe() const; diff --git a/src/main_data.cpp b/src/main_data.cpp index 86d4a8cc31..33a6a8ff01 100644 --- a/src/main_data.cpp +++ b/src/main_data.cpp @@ -41,9 +41,12 @@ #include "system.h" #include "output.h" -#ifndef _WIN32 +#ifdef _WIN32 +# include <windows.h> +#else # include <unistd.h> #endif + #if defined(USE_SDL) && defined(__ANDROID__) # include <jni.h> # include <SDL_system.h> @@ -89,22 +92,27 @@ void Main_Data::Init() { // Set to current directory project_path = ""; -#if defined(PLAYER_AMIGA) - // Working directory not correctly handled - char working_dir[256]; - getcwd(working_dir, 255); - project_path = std::string(working_dir); -#elif defined(__APPLE__) && TARGET_OS_OSX +#ifdef _WIN32 + wchar_t working_dir[MAX_PATH]; + if (GetCurrentDirectory(MAX_PATH, working_dir) != 0) { + project_path = Utils::FromWideString(working_dir); + } +#else + char working_dir[PATH_MAX]; + if (getcwd(working_dir, sizeof(working_dir))) { + project_path = std::string(working_dir); + } + +# if defined(__APPLE__) && TARGET_OS_OSX // Apple Finder does not set the working directory // It points to HOME instead. When it is HOME change it to // the application directory instead char* home = getenv("HOME"); - char current_dir[PATH_MAX] = { 0 }; - getcwd(current_dir, sizeof(current_dir)); - if (strcmp(current_dir, "/") == 0 || strcmp(current_dir, home) == 0) { + if (strcmp(working_dir, "/") == 0 || strcmp(working_dir, home) == 0) { project_path = MacOSUtils::GetBundleDir(); } +# endif #endif } } diff --git a/src/scene_gamebrowser.cpp b/src/scene_gamebrowser.cpp index 5a0b700569..06b731b8f5 100644 --- a/src/scene_gamebrowser.cpp +++ b/src/scene_gamebrowser.cpp @@ -99,9 +99,9 @@ void Scene_GameBrowser::CreateWindows() { command_window->SetIndex(0); gamelist_window = std::make_unique<Window_GameList>(0, 64, Player::screen_width, Player::screen_height - 64); - gamelist_window->Refresh(stack.back().filesystem, false); + gamelist_window->Refresh(stack.back().filesystem, stack.back().filesystem.CanGoUp()); - if (stack.size() == 1 && !gamelist_window->HasValidEntry()) { + if (stack.size() == 1 && !stack.back().filesystem.CanGoUp() && !gamelist_window->HasValidEntry()) { command_window->DisableItem(0); } @@ -140,7 +140,7 @@ void Scene_GameBrowser::UpdateCommand() { switch (menu_index) { case GameList: - if (stack.size() == 1 && !gamelist_window->HasValidEntry()) { + if (!command_window->IsItemEnabled(0)) { return; } command_window->SetActive(false); @@ -177,11 +177,17 @@ void Scene_GameBrowser::UpdateGameListSelection() { } void Scene_GameBrowser::BootGame() { - if (stack.size() > 1 && gamelist_window->GetIndex() == 0) { + if (stack.back().filesystem.CanGoUp() && gamelist_window->GetIndex() == 0) { // ".." -> Go one level up int index = stack.back().index; - stack.pop_back(); - gamelist_window->Refresh(stack.back().filesystem, stack.size() > 1); + + if (stack.size() == 1) { + stack.back() = {stack.back().filesystem.GoUp(), 0}; + } else { + stack.pop_back(); + } + + gamelist_window->Refresh(stack.back().filesystem, stack.back().filesystem.CanGoUp()); gamelist_window->SetIndex(index); load_window->SetVisible(false); game_loading = false; diff --git a/src/window_gamelist.cpp b/src/window_gamelist.cpp index bf6b58fed0..7a0d2c7ce0 100644 --- a/src/window_gamelist.cpp +++ b/src/window_gamelist.cpp @@ -111,6 +111,12 @@ void Window_GameList::DrawItem(int index) { contents->TextDraw(rect.x, rect.y, Font::ColorDefault, game_directories[index]); } +#ifdef HAVE_LHASA +#define LZH_STR "/LZH" +#else +#define LZH_STR "" +#endif + void Window_GameList::DrawErrorText(bool show_dotdot) { std::vector<std::string> error_msg = { #ifdef EMSCRIPTEN @@ -128,7 +134,7 @@ void Window_GameList::DrawErrorText(bool show_dotdot) { "with RPG Maker 2000 and RPG Maker 2003.", "", "These games have an RPG_RT.ldb and they can be", - "extracted or in ZIP archives.", + "extracted or in ZIP" LZH_STR " archives.", "", "Newer engines such as RPG Maker XP, VX, MV and MZ", "are not supported." diff --git a/tests/filefinder.cpp b/tests/filefinder.cpp index 60cabf16d8..b40f931c04 100644 --- a/tests/filefinder.cpp +++ b/tests/filefinder.cpp @@ -8,8 +8,6 @@ TEST_SUITE_BEGIN("FileFinder"); TEST_CASE("IsRPG2kProject") { - Main_Data::Init(); - Player::escape_symbol = "\\"; auto fs = FileFinder::Root().Subtree(EP_TEST_PATH "/game"); @@ -19,8 +17,6 @@ TEST_CASE("IsRPG2kProject") { } TEST_CASE("IsNotRPG2kProject") { - Main_Data::Init(); - auto fs = FileFinder::Root().Subtree(EP_TEST_PATH "/notagame"); CHECK(!FileFinder::IsRPG2kProject(fs)); } diff --git a/tests/output.cpp b/tests/output.cpp index 0305c06768..33bf759247 100644 --- a/tests/output.cpp +++ b/tests/output.cpp @@ -7,7 +7,6 @@ TEST_SUITE_BEGIN("Output"); TEST_CASE("Message Output") { Graphics::Init(); - Main_Data::Init(); Output::Debug("Test {}", "debg"); Output::Warning("Test {}", "test"); Output::Info("Test {}", "info"); From 3bba5b9effd1c57163a2c1afaac01b23ba464446 Mon Sep 17 00:00:00 2001 From: Ghabry <gabriel+github@mastergk.de> Date: Mon, 1 Apr 2024 17:50:25 +0200 Subject: [PATCH 2/5] Add Drive Filesystem Is a virtual filesystem that lists drive letters on e.g. Windows. The filesystem is deactivated on all other platforms right now. Invented a new filetype "Filesystem" for delegation of the drive FS to the native FS. This is kinda a hack but I couldn't think of a better way to add this... --- CMakeLists.txt | 2 + Makefile.am | 2 + src/directory_tree.h | 9 ++++ src/filesystem.cpp | 32 +++++++++-- src/filesystem.h | 16 ++++++ src/filesystem_drive.cpp | 110 ++++++++++++++++++++++++++++++++++++++ src/filesystem_drive.h | 56 +++++++++++++++++++ src/filesystem_root.cpp | 15 ++++-- src/scene_gamebrowser.cpp | 4 +- src/window_gamelist.cpp | 22 ++++---- src/window_gamelist.h | 6 +-- 11 files changed, 251 insertions(+), 23 deletions(-) create mode 100644 src/filesystem_drive.cpp create mode 100644 src/filesystem_drive.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 88c93137a9..86b309cc2a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -120,6 +120,8 @@ add_library(${PROJECT_NAME} OBJECT src/fileext_guesser.h src/filesystem.cpp src/filesystem.h + src/filesystem_drive.cpp + src/filesystem_drive.h src/filesystem_lzh.cpp src/filesystem_lzh.h src/filesystem_native.cpp diff --git a/Makefile.am b/Makefile.am index c05af3518a..0390b833b2 100644 --- a/Makefile.am +++ b/Makefile.am @@ -103,6 +103,8 @@ libeasyrpg_player_a_SOURCES = \ src/fileext_guesser.h \ src/filesystem.cpp \ src/filesystem.h \ + src/filesystem_drive.cpp \ + src/filesystem_drive.h \ src/filesystem_lzh.cpp \ src/filesystem_lzh.h \ src/filesystem_native.cpp \ diff --git a/src/directory_tree.h b/src/directory_tree.h index 6232f5814e..71f72ba50f 100644 --- a/src/directory_tree.h +++ b/src/directory_tree.h @@ -43,6 +43,8 @@ class DirectoryTree { Regular, /** Directory */ Directory, + /** A virtual directory that will access a different virtual filesystem */ + Filesystem, /** Anything of no interest such as block devices */ Other }; @@ -53,8 +55,15 @@ class DirectoryTree { std::string name; /** File type */ FileType type; + /** Human readable name shown in the Game Browser (if different to the filename) */ + std::string human_name; Entry(std::string name, FileType type) : name(std::move(name)), type(type) {} + Entry(std::string name, FileType type, std::string human_name) : name(std::move(name)), type(type), human_name(std::move(human_name)) {} + + StringView GetReadableName() const { + return human_name.empty() ? name : human_name; + } }; /** Argument struct for more complex find operations */ diff --git a/src/filesystem.cpp b/src/filesystem.cpp index a6757392a6..1649512b5f 100644 --- a/src/filesystem.cpp +++ b/src/filesystem.cpp @@ -87,9 +87,13 @@ void Filesystem::ClearCache(StringView path) const { FilesystemView Filesystem::Create(StringView path) const { // Determine the proper file system to use - // When the path doesn't exist check if the path contains a file that can - // be handled by another filesystem - if (!IsDirectory(path, true)) { + if (IsFilesystemNode(path)) { + // The support for "mounted" virtual filesystems is very limited and the only + // use right now is to delegate from DriveFilesystem to NativeFilesystem. + return CreateFromNode(path); + } else if (!IsDirectory(path, true)) { + // When the path doesn't exist check if the path contains a file that can + // be handled by another filesystem std::string dir_of_file; std::string path_prefix; std::vector<std::string> components = FileFinder::SplitPath(path); @@ -175,10 +179,18 @@ FilesystemView Filesystem::Subtree(std::string sub_path) const { return FilesystemView(shared_from_this(), sub_path); } +bool Filesystem::IsFilesystemNode(StringView) const { + return false; +} + bool Filesystem::MakeDirectory(StringView, bool) const { return false; } +FilesystemView Filesystem::CreateFromNode(StringView) const { + return FilesystemView(); +} + bool Filesystem::IsValid() const { // FIXME: better way to do this? return Exists(""); @@ -307,6 +319,11 @@ bool FilesystemView::IsDirectory(StringView path, bool follow_symlinks) const { return fs->IsDirectory(MakePath(path), follow_symlinks); } +bool FilesystemView::IsFilesystemNode(StringView path) const { + assert(fs); + return fs->IsFilesystemNode(MakePath(path)); +} + bool FilesystemView::Exists(StringView path) const { assert(fs); return fs->Exists(MakePath(path)); @@ -372,6 +389,11 @@ bool FilesystemView::MakeDirectory(StringView dir, bool follow_symlinks) const { return fs->MakeDirectory(MakePath(dir), follow_symlinks); } +FilesystemView FilesystemView::CreateFromNode(StringView path) const { + assert(fs); + return fs->CreateFromNode(MakePath(path)); +} + bool FilesystemView::IsFeatureSupported(Filesystem::Feature f) const { assert(fs); return fs->IsFeatureSupported(f); @@ -393,6 +415,10 @@ FilesystemView FilesystemView::GoUp() const { auto [path, file] = FileFinder::GetPathAndFilename(GetSubPath()); + if (path == GetSubPath()) { + return fs->GetParent(); + } + return FilesystemView(fs, path); } diff --git a/src/filesystem.h b/src/filesystem.h index 736d476016..096deca019 100644 --- a/src/filesystem.h +++ b/src/filesystem.h @@ -217,9 +217,11 @@ class Filesystem : public std::enable_shared_from_this<Filesystem> { /** @{ */ virtual bool IsFile(StringView path) const = 0; virtual bool IsDirectory(StringView path, bool follow_symlinks) const = 0; + virtual bool IsFilesystemNode(StringView path) const; virtual bool Exists(StringView path) const = 0; virtual int64_t GetFilesize(StringView path) const = 0; virtual bool MakeDirectory(StringView dir, bool follow_symlinks) const; + virtual FilesystemView CreateFromNode(StringView path) const; virtual bool IsFeatureSupported(Feature f) const; virtual std::string Describe() const = 0; /** @} */ @@ -369,6 +371,12 @@ class FilesystemView { */ bool IsDirectory(StringView path, bool follow_symlinks) const; + /** + * @param path Path to check + * @return True when path is pointing to a virtual filesystem + */ + bool IsFilesystemNode(StringView path) const; + /** * @param path Path to check * @return True when a file exists at the path @@ -461,6 +469,14 @@ class FilesystemView { */ bool MakeDirectory(StringView dir, bool follow_symlinks) const; + /** + * Create a filesystem view from the passed in path. + * The path must point to a virtual filesystem entry (type Filesystem). + * @param path Path to create filesystem from + * @return view pointing at the new fs + */ + FilesystemView CreateFromNode(StringView path) const; + /** * @param f Filesystem feature to check * @return true when the feature is supported. diff --git a/src/filesystem_drive.cpp b/src/filesystem_drive.cpp new file mode 100644 index 0000000000..67aced70f4 --- /dev/null +++ b/src/filesystem_drive.cpp @@ -0,0 +1,110 @@ +/* + * This file is part of EasyRPG Player. + * + * EasyRPG Player is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * EasyRPG Player is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with EasyRPG Player. If not, see <http://www.gnu.org/licenses/>. + */ + +#include "filesystem_drive.h" +#include "filefinder.h" +#include "output.h" + +#include <algorithm> + +#ifdef _WIN32 +# include <windows.h> +# include <fileapi.h> +#endif + +DriveFilesystem::DriveFilesystem() : Filesystem("", FilesystemView()) { +#ifdef _WIN32 + std::wstring volume = L"A:\\"; + + DWORD logical_drives = GetLogicalDrives(); + for (int i = 0; i < 26; i++) { + if ((logical_drives & (1 << i)) > 0) { + DirectoryTree::Entry entry = { Utils::FromWideString(volume), DirectoryTree::FileType::Filesystem }; + + wchar_t volume_name[MAX_PATH]; + if (GetVolumeInformation(volume.c_str(), volume_name, MAX_PATH, nullptr, nullptr, nullptr, nullptr, 0) != 0) { + entry.human_name = fmt::format("{} ({})", Utils::FromWideString(volume), Utils::FromWideString(volume_name)); + } + + drives.push_back(entry); + } + volume[0]++; // Increment drive letter + } +#endif +} + +bool DriveFilesystem::HasDrives() const { + return !drives.empty(); +} + +bool DriveFilesystem::IsFile(StringView path) const { + (void)path; + return false; +} + +bool DriveFilesystem::IsDirectory(StringView path, bool) const { + return path.empty(); +} + +bool DriveFilesystem::IsFilesystemNode(StringView path) const { + for (const auto& drive: drives) { + if (drive.name == path) { + return true; + } +#ifdef _WIN32 + if (drive.name == Utils::ReplaceAll(ToString(path), "/", "\\")) { + return true; + } +#endif + } + + return false; +} + +bool DriveFilesystem::Exists(StringView path) const { + return IsDirectory(path, false) || IsFilesystemNode(path); +} + +int64_t DriveFilesystem::GetFilesize(StringView path) const { + (void)path; + return 0; +} + +FilesystemView DriveFilesystem::CreateFromNode(StringView path) const { + if (!IsFilesystemNode(path)) { + return {}; + } + + return FileFinder::Root().Create(path); +} + +std::streambuf* DriveFilesystem::CreateInputStreambuffer(StringView path, std::ios_base::openmode mode) const { + return nullptr; +} + +bool DriveFilesystem::GetDirectoryContent(StringView path, std::vector<DirectoryTree::Entry>& tree) const { + if (!path.empty()) { + return false; + } + + tree = drives; + return true; +} + +std::string DriveFilesystem::Describe() const { + return "[Drive]"; +} diff --git a/src/filesystem_drive.h b/src/filesystem_drive.h new file mode 100644 index 0000000000..83985f9ee9 --- /dev/null +++ b/src/filesystem_drive.h @@ -0,0 +1,56 @@ +/* + * This file is part of EasyRPG Player. + * + * EasyRPG Player is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * EasyRPG Player is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with EasyRPG Player. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef EP_FILESYSTEM_DRIVE_H +#define EP_FILESYSTEM_DRIVE_H + +#include "filesystem.h" + +/** + * A virtual filesystem that lists e.g. drive letters on Windows + */ +class DriveFilesystem : public Filesystem { +public: + /** + * Initializes a OS Filesystem on the given os path + */ + explicit DriveFilesystem(); + + /** @return Whether the current target platform has drive letters to list */ + bool HasDrives() const; + +protected: + /** + * Implementation of abstract methods + */ + /** @{ */ + bool IsFile(StringView path) const override; + bool IsDirectory(StringView path, bool follow_symlinks) const override; + bool IsFilesystemNode(StringView path) const override; + bool Exists(StringView path) const override; + int64_t GetFilesize(StringView path) const override; + FilesystemView CreateFromNode(StringView path) const override; + std::streambuf* CreateInputStreambuffer(StringView path, std::ios_base::openmode mode) const override; + bool GetDirectoryContent(StringView path, std::vector<DirectoryTree::Entry>& entries) const override; + std::string Describe() const override; + /** @} */ + +private: + std::vector<DirectoryTree::Entry> drives; +}; + +#endif diff --git a/src/filesystem_root.cpp b/src/filesystem_root.cpp index 270c6efa7f..4270cfcd47 100644 --- a/src/filesystem_root.cpp +++ b/src/filesystem_root.cpp @@ -16,6 +16,7 @@ */ #include "filesystem_root.h" +#include "filesystem_drive.h" #include "output.h" #if defined(__ANDROID__) && !defined(USE_LIBRETRO) @@ -28,12 +29,20 @@ constexpr const StringView root_ns = "root://"; RootFilesystem::RootFilesystem() : Filesystem("", FilesystemView()) { // Add platform specific namespaces here #if defined(__ANDROID__) && !defined(USE_LIBRETRO) - fs_list.push_back(std::make_pair("apk", std::make_unique<ApkFilesystem>())); - fs_list.push_back(std::make_pair("content", std::make_unique<SafFilesystem>("", FilesystemView()))); + fs_list.push_back(std::make_pair("apk", std::make_shared<ApkFilesystem>())); + fs_list.push_back(std::make_pair("content", std::make_shared<SafFilesystem>("", FilesystemView()))); #endif + // Support for drive letters on e.g. Windows (and similiar concepts on other platforms) + auto drive_fs = std::make_shared<DriveFilesystem>(); + FilesystemView drive_view; + if (drive_fs->HasDrives()) { + drive_view = *drive_fs; + fs_list.push_back(std::make_pair("drive", drive_fs)); + } + // IMPORTANT: This must be the last filesystem in the list, do not push anything to fs_list afterwards! - fs_list.push_back(std::make_pair("file", std::make_unique<NativeFilesystem>("", FilesystemView()))); + fs_list.push_back(std::make_pair("file", std::make_shared<NativeFilesystem>("", drive_view))); assert(fs_list.back().first == "file" && "File namespace must be last!"); } diff --git a/src/scene_gamebrowser.cpp b/src/scene_gamebrowser.cpp index 06b731b8f5..38562e49cd 100644 --- a/src/scene_gamebrowser.cpp +++ b/src/scene_gamebrowser.cpp @@ -194,9 +194,7 @@ void Scene_GameBrowser::BootGame() { return; } - FilesystemView fs; - std::string entry; - std::tie(fs, entry) = gamelist_window->GetGameFilesystem(); + FilesystemView fs = gamelist_window->GetGameFilesystem(); if (!fs) { Output::Warning("The selected file or directory cannot be opened"); diff --git a/src/window_gamelist.cpp b/src/window_gamelist.cpp index 7a0d2c7ce0..35c89d7af4 100644 --- a/src/window_gamelist.cpp +++ b/src/window_gamelist.cpp @@ -55,21 +55,21 @@ bool Window_GameList::Refresh(FilesystemView filesystem_base, bool show_dotdot) } if (dir.second.type == DirectoryTree::FileType::Regular) { if (FileFinder::IsSupportedArchiveExtension(dir.second.name)) { - game_directories.emplace_back(dir.second.name); + game_directories.emplace_back(dir.second); } - } else if (dir.second.type == DirectoryTree::FileType::Directory) { - game_directories.emplace_back(dir.second.name); + } else if (dir.second.type == DirectoryTree::FileType::Directory || dir.second.type == DirectoryTree::FileType::Filesystem) { + game_directories.emplace_back(dir.second); } } // Sort game list in place std::sort(game_directories.begin(), game_directories.end(), - [](const std::string& s, const std::string& s2) { - return strcmp(Utils::LowerCase(s).c_str(), Utils::LowerCase(s2).c_str()) <= 0; + [](DirectoryTree::Entry& s, DirectoryTree::Entry& s2) { + return strcmp(Utils::LowerCase(s.GetReadableName()).c_str(), Utils::LowerCase(s2.GetReadableName()).c_str()) <= 0; }); if (show_dotdot) { - game_directories.insert(game_directories.begin(), ".."); + game_directories.insert(game_directories.begin(), { "..", DirectoryTree::FileType::Directory }); } if (HasValidEntry()) { @@ -102,13 +102,13 @@ void Window_GameList::DrawItem(int index) { Rect rect = GetItemRect(index); contents->ClearRect(rect); - std::string text; + StringView text; if (HasValidEntry()) { - text = game_directories[index]; + text = game_directories[index].GetReadableName(); } - contents->TextDraw(rect.x, rect.y, Font::ColorDefault, game_directories[index]); + contents->TextDraw(rect.x, rect.y, Font::ColorDefault, text); } #ifdef HAVE_LHASA @@ -160,6 +160,6 @@ bool Window_GameList::HasValidEntry() { return game_directories.size() > minval; } -std::pair<FilesystemView, std::string> Window_GameList::GetGameFilesystem() const { - return { base_fs.Create(game_directories[GetIndex()]), game_directories[GetIndex()] }; +FilesystemView Window_GameList::GetGameFilesystem() const { + return base_fs.Create(game_directories[GetIndex()].name); } diff --git a/src/window_gamelist.h b/src/window_gamelist.h index a3809c6f86..4e27c47595 100644 --- a/src/window_gamelist.h +++ b/src/window_gamelist.h @@ -55,13 +55,13 @@ class Window_GameList : public Window_Selectable { bool HasValidEntry(); /** - * @return filesystem and entry name of the selected game + * @return filesystem of the selected game */ - std::pair<FilesystemView, std::string> GetGameFilesystem() const; + FilesystemView GetGameFilesystem() const; private: FilesystemView base_fs; - std::vector<std::string> game_directories; + std::vector<DirectoryTree::Entry> game_directories; bool show_dotdot = false; }; From ec57bb4ceeaaef205871bf61b1700fedc7c23d6c Mon Sep 17 00:00:00 2001 From: Ghabry <gabriel+github@mastergk.de> Date: Mon, 1 Apr 2024 18:14:00 +0200 Subject: [PATCH 3/5] Windows: Check for correct error value for directories --- src/platform.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/platform.h b/src/platform.h index a285822c7f..dacba8047c 100644 --- a/src/platform.h +++ b/src/platform.h @@ -157,6 +157,8 @@ namespace Platform { inline Directory::operator bool() const noexcept { #ifdef __vita__ return dir_handle >= 0; +#elif defined(_WIN32) + return dir_handle != INVALID_HANDLE_VALUE; #else return dir_handle != nullptr; #endif From ebdd6c87a82fea06dd09b0a4a48590a37e717df3 Mon Sep 17 00:00:00 2001 From: Ghabry <gabriel+github@mastergk.de> Date: Mon, 1 Apr 2024 20:51:51 +0200 Subject: [PATCH 4/5] Fix Vita build (PATH_MAX not defined) --- src/main_data.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/main_data.cpp b/src/main_data.cpp index 33a6a8ff01..8dd1ef6bb9 100644 --- a/src/main_data.cpp +++ b/src/main_data.cpp @@ -98,6 +98,10 @@ void Main_Data::Init() { project_path = Utils::FromWideString(working_dir); } #else + +# ifndef PATH_MAX +# define PATH_MAX 256 +# endif char working_dir[PATH_MAX]; if (getcwd(working_dir, sizeof(working_dir))) { project_path = std::string(working_dir); From 1a24b49f184017e252ed80be64126fea62c3b525 Mon Sep 17 00:00:00 2001 From: Ghabry <gabriel+github@mastergk.de> Date: Mon, 1 Apr 2024 20:52:30 +0200 Subject: [PATCH 5/5] Emscripten: Do not show ".." on error screen. Other platforms: Fix rendering of ".." on error screen. --- src/scene_gamebrowser.cpp | 4 ++++ src/window_gamelist.cpp | 11 +++++------ 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/src/scene_gamebrowser.cpp b/src/scene_gamebrowser.cpp index 38562e49cd..9c0f889b75 100644 --- a/src/scene_gamebrowser.cpp +++ b/src/scene_gamebrowser.cpp @@ -105,6 +105,10 @@ void Scene_GameBrowser::CreateWindows() { command_window->DisableItem(0); } +#ifdef EMSCRIPTEN + command_window->DisableItem(0); +#endif + help_window = std::make_unique<Window_Help>(0, 0, Player::screen_width, 32); help_window->SetText("EasyRPG Player - RPG Maker 2000/2003 interpreter"); diff --git a/src/window_gamelist.cpp b/src/window_gamelist.cpp index 35c89d7af4..3daee9ef13 100644 --- a/src/window_gamelist.cpp +++ b/src/window_gamelist.cpp @@ -84,6 +84,10 @@ bool Window_GameList::Refresh(FilesystemView filesystem_base, bool show_dotdot) } } else { +#ifdef EMSCRIPTEN + show_dotdot = false; +#endif + item_max = 1; SetContents(Bitmap::Create(width - 16, height - 16)); @@ -102,12 +106,7 @@ void Window_GameList::DrawItem(int index) { Rect rect = GetItemRect(index); contents->ClearRect(rect); - StringView text; - - if (HasValidEntry()) { - text = game_directories[index].GetReadableName(); - } - + StringView text = game_directories[index].GetReadableName(); contents->TextDraw(rect.x, rect.y, Font::ColorDefault, text); }