diff --git a/src/common/config.cpp b/src/common/config.cpp index fb6ee120a..fb4acac1b 100644 --- a/src/common/config.cpp +++ b/src/common/config.cpp @@ -4,6 +4,7 @@ #include #include #include +#include // for wstring support #include #include "config.h" @@ -444,11 +445,18 @@ void save(const std::filesystem::path& path) { return; } } else { +#ifdef _WIN32 +#define PREFIX(str) L##str +#else +#define PREFIX(str) str +#endif if (error) { - fmt::print("Filesystem error accessing {} (error: {})\n", path.string(), - error.message().c_str()); + fmt::print(PREFIX("Filesystem error accessing {}"), path.native()); + // can't mix wstring and string in fmt + fmt::print(" (error: {})\n", error.message()); } - fmt::print("Saving new configuration file {}\n", path.string()); + fmt::print(PREFIX("Saving new configuration file {}\n"), path.native()); +#undef PREFIX } data["General"]["isPS4Pro"] = isNeo; diff --git a/src/common/memory_patcher.cpp b/src/common/memory_patcher.cpp index 85a25167a..d2930cf5e 100644 --- a/src/common/memory_patcher.cpp +++ b/src/common/memory_patcher.cpp @@ -119,9 +119,9 @@ std::string convertValueToHex(const std::string type, const std::string valueStr void OnGameLoaded() { if (!patchFile.empty()) { - std::string patchDir = Common::FS::GetUserPath(Common::FS::PathType::PatchesDir).string(); + std::filesystem::path patchDir = Common::FS::GetUserPath(Common::FS::PathType::PatchesDir); - std::string filePath = patchDir + "/" + patchFile; + auto filePath = (patchDir / patchFile).native(); pugi::xml_document doc; pugi::xml_parse_result result = doc.load_file(filePath.c_str()); @@ -187,8 +187,8 @@ void OnGameLoaded() { #ifdef ENABLE_QT_GUI // We use the QT headers for the xml and json parsing, this define is only true on QT builds - QString patchDir = - QString::fromStdString(Common::FS::GetUserPath(Common::FS::PathType::PatchesDir).string()); + QString patchDir; + Common::FS::PathToQString(patchDir, Common::FS::GetUserPath(Common::FS::PathType::PatchesDir)); QString repositories[] = {"GoldHEN", "shadPS4"}; for (const QString& repository : repositories) { diff --git a/src/common/path_util.cpp b/src/common/path_util.cpp index cce12ebcf..d7274fc74 100644 --- a/src/common/path_util.cpp +++ b/src/common/path_util.cpp @@ -22,6 +22,10 @@ #endif #endif +#ifdef ENABLE_QT_GUI +#include +#endif + namespace Common::FS { namespace fs = std::filesystem; @@ -165,4 +169,22 @@ void SetUserPath(PathType shad_path, const fs::path& new_path) { UserPaths.insert_or_assign(shad_path, new_path); } +#ifdef ENABLE_QT_GUI +void PathToQString(QString& result, const std::filesystem::path& path) { +#ifdef _WIN32 + result = QString::fromStdWString(path.wstring()); +#else + result = QString::fromStdString(path.string()); +#endif +} + +std::filesystem::path PathFromQString(const QString& path) { +#ifdef _WIN32 + return std::filesystem::path(path.toStdWString()); +#else + return std::filesystem::path(path.toStdString()); +#endif +} +#endif + } // namespace Common::FS \ No newline at end of file diff --git a/src/common/path_util.h b/src/common/path_util.h index 623b285ed..d40f4aab4 100644 --- a/src/common/path_util.h +++ b/src/common/path_util.h @@ -6,6 +6,10 @@ #include #include +#ifdef ENABLE_QT_GUI +class QString; // to avoid including in this header +#endif + namespace Common::FS { enum class PathType { @@ -96,4 +100,23 @@ constexpr auto LOG_FILE = "shad_log.txt"; */ void SetUserPath(PathType user_path, const std::filesystem::path& new_path); +#ifdef ENABLE_QT_GUI +/** + * Converts an std::filesystem::path to a QString. + * The native underlying string of a path is wstring on Windows and string on POSIX. + * + * @param result The resulting QString + * @param path The path to convert + */ +void PathToQString(QString& result, const std::filesystem::path& path); + +/** + * Converts a QString to an std::filesystem::path. + * The native underlying string of a path is wstring on Windows and string on POSIX. + * + * @param path The path to convert + */ +[[nodiscard]] std::filesystem::path PathFromQString(const QString& path); +#endif + } // namespace Common::FS diff --git a/src/core/file_format/pkg.cpp b/src/core/file_format/pkg.cpp index d86f3b28d..f329e81a6 100644 --- a/src/core/file_format/pkg.cpp +++ b/src/core/file_format/pkg.cpp @@ -371,8 +371,7 @@ bool PKG::Extract(const std::filesystem::path& filepath, const std::filesystem:: if (table.type == PFS_CURRENT_DIR) { current_dir = extractPaths[table.inode]; } - extractPaths[table.inode] = - current_dir.string() / std::filesystem::path(table.name); + extractPaths[table.inode] = current_dir / std::filesystem::path(table.name); if (table.type == PFS_FILE || table.type == PFS_DIR) { if (table.type == PFS_DIR) { // Create dirs. @@ -402,7 +401,7 @@ void PKG::ExtractFiles(const int index) { int bsize = iNodeBuf[inode_number].Size; Common::FS::IOFile inflated; - inflated.Open(extractPaths[inode_number].string(), Common::FS::FileAccessMode::Write); + inflated.Open(extractPaths[inode_number], Common::FS::FileAccessMode::Write); Common::FS::IOFile pkgFile; // Open the file for each iteration to avoid conflict. pkgFile.Open(pkgpath, Common::FS::FileAccessMode::Read); diff --git a/src/core/file_format/splash.cpp b/src/core/file_format/splash.cpp index f41789a85..5e06c912d 100644 --- a/src/core/file_format/splash.cpp +++ b/src/core/file_format/splash.cpp @@ -12,8 +12,8 @@ #define STBI_NO_STDIO #include "externals/stb_image.h" -bool Splash::Open(const std::string& filepath) { - ASSERT_MSG(filepath.ends_with(".png"), "Unexpected file format passed"); +bool Splash::Open(const std::filesystem::path& filepath) { + ASSERT_MSG(filepath.stem().string() != "png", "Unexpected file format passed"); Common::FS::IOFile file(filepath, Common::FS::FileAccessMode::Read); if (!file.IsOpen()) { diff --git a/src/core/file_format/splash.h b/src/core/file_format/splash.h index 68cc33c47..7c563f317 100644 --- a/src/core/file_format/splash.h +++ b/src/core/file_format/splash.h @@ -3,6 +3,7 @@ #pragma once +#include #include #include #include "common/types.h" @@ -22,7 +23,7 @@ public: Splash() = default; ~Splash() = default; - bool Open(const std::string& filepath); + bool Open(const std::filesystem::path& filepath); [[nodiscard]] bool IsLoaded() const { return img_data.size(); } diff --git a/src/core/file_format/trp.cpp b/src/core/file_format/trp.cpp index 86865fe63..724f90782 100644 --- a/src/core/file_format/trp.cpp +++ b/src/core/file_format/trp.cpp @@ -29,7 +29,7 @@ static void removePadding(std::vector& vec) { } bool TRP::Extract(const std::filesystem::path& trophyPath) { - std::string title = trophyPath.filename().string(); + std::filesystem::path title = trophyPath.filename(); std::filesystem::path gameSysDir = trophyPath / "sce_sys/trophy/"; if (!std::filesystem::exists(gameSysDir)) { return false; diff --git a/src/emulator.cpp b/src/emulator.cpp index 4a2e38ff8..e68fb8f18 100644 --- a/src/emulator.cpp +++ b/src/emulator.cpp @@ -139,7 +139,7 @@ void Emulator::Run(const std::filesystem::path& file) { if (splash->IsLoaded()) { continue; } - if (!splash->Open(entry.path().string())) { + if (!splash->Open(entry.path())) { LOG_ERROR(Loader, "Game splash: unable to open file"); } } diff --git a/src/imgui/renderer/imgui_core.cpp b/src/imgui/renderer/imgui_core.cpp index b972d99d0..d41097d7c 100644 --- a/src/imgui/renderer/imgui_core.cpp +++ b/src/imgui/renderer/imgui_core.cpp @@ -51,8 +51,14 @@ void Initialize(const ::Vulkan::Instance& instance, const Frontend::WindowSDL& w io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad; io.ConfigFlags |= ImGuiConfigFlags_DockingEnable; io.DisplaySize = ImVec2((float)window.getWidth(), (float)window.getHeight()); - io.IniFilename = SDL_strdup(config_path.string().c_str()); - io.LogFilename = SDL_strdup(log_path.string().c_str()); + + using native_char = std::filesystem::path::value_type; + io.IniFilename = new char[config_path.native().size() * sizeof(native_char)]; + io.LogFilename = new char[log_path.native().size() * sizeof(native_char)]; + std::memcpy((void*)io.IniFilename, config_path.native().c_str(), + config_path.native().size() * sizeof(native_char)); + std::memcpy((void*)io.LogFilename, log_path.native().c_str(), + log_path.native().size() * sizeof(native_char)); ImFontGlyphRangesBuilder rb{}; rb.AddRanges(io.Fonts->GetGlyphRangesDefault()); diff --git a/src/qt_gui/cheats_patches.cpp b/src/qt_gui/cheats_patches.cpp index a58106cb3..127ff2c85 100644 --- a/src/qt_gui/cheats_patches.cpp +++ b/src/qt_gui/cheats_patches.cpp @@ -50,8 +50,9 @@ void CheatsPatches::setupUI() { defaultTextEdit = tr("defaultTextEdit_MSG"); defaultTextEdit.replace("\\n", "\n"); - QString CHEATS_DIR_QString = - QString::fromStdString(Common::FS::GetUserPath(Common::FS::PathType::CheatsDir).string()); + QString CHEATS_DIR_QString; + Common::FS::PathToQString(CHEATS_DIR_QString, + Common::FS::GetUserPath(Common::FS::PathType::CheatsDir)); QString NameCheatJson = m_gameSerial + "_" + m_gameVersion + ".json"; m_cheatFilePath = CHEATS_DIR_QString + "/" + NameCheatJson; @@ -275,9 +276,9 @@ void CheatsPatches::onSaveButtonClicked() { int separatorIndex = selectedPatchName.indexOf(" | "); selectedPatchName = selectedPatchName.mid(separatorIndex + 3); - QString patchDir = - QString::fromStdString(Common::FS::GetUserPath(Common::FS::PathType::PatchesDir).string()) + - "/" + selectedPatchName; + QString patchDir; + Common::FS::PathToQString(patchDir, Common::FS::GetUserPath(Common::FS::PathType::PatchesDir)); + patchDir += "/" + selectedPatchName; QString filesJsonPath = patchDir + "/files.json"; QFile jsonFile(filesJsonPath); @@ -555,10 +556,10 @@ void CheatsPatches::downloadCheats(const QString& source, const QString& gameSer if (dotIndex != -1) { baseFileName.insert(dotIndex, "_wolf2022"); } - QString filePath = - QString::fromStdString( - Common::FS::GetUserPath(Common::FS::PathType::CheatsDir).string()) + - "/" + baseFileName; + QString filePath; + Common::FS::PathToQString(filePath, + Common::FS::GetUserPath(Common::FS::PathType::CheatsDir)); + filePath += "/" + baseFileName; if (QFile::exists(filePath) && showMessageBox) { QMessageBox::StandardButton reply2; reply2 = @@ -612,8 +613,9 @@ void CheatsPatches::populateFileListPatches() { } m_patchInfos.clear(); - QString patchesDir = - QString::fromStdString(Common::FS::GetUserPath(Common::FS::PathType::PatchesDir).string()); + QString patchesDir; + Common::FS::PathToQString(patchesDir, + Common::FS::GetUserPath(Common::FS::PathType::PatchesDir)); QDir dir(patchesDir); QStringList folders = dir.entryList(QDir::Dirs | QDir::NoDotAndDotDot); @@ -906,8 +908,8 @@ void CheatsPatches::addCheatsToLayout(const QJsonArray& modsArray, const QJsonAr } void CheatsPatches::populateFileListCheats() { - QString cheatsDir = - QString::fromStdString(Common::FS::GetUserPath(Common::FS::PathType::CheatsDir).string()); + QString cheatsDir; + Common::FS::PathToQString(cheatsDir, Common::FS::GetUserPath(Common::FS::PathType::CheatsDir)); QString pattern = m_gameSerial + "_" + m_gameVersion + "*.json"; QDir dir(cheatsDir); @@ -932,8 +934,9 @@ void CheatsPatches::populateFileListCheats() { if (!selectedIndexes.isEmpty()) { QString selectedFileName = selectedIndexes.first().data().toString(); - QString cheatsDir = QString::fromStdString( - Common::FS::GetUserPath(Common::FS::PathType::CheatsDir).string()); + QString cheatsDir; + Common::FS::PathToQString( + cheatsDir, Common::FS::GetUserPath(Common::FS::PathType::CheatsDir)); QFile file(cheatsDir + "/" + selectedFileName); if (file.open(QIODevice::ReadOnly)) { diff --git a/src/qt_gui/game_grid_frame.cpp b/src/qt_gui/game_grid_frame.cpp index 9fba0c47c..2b2d4ec71 100644 --- a/src/qt_gui/game_grid_frame.cpp +++ b/src/qt_gui/game_grid_frame.cpp @@ -116,11 +116,8 @@ void GameGridFrame::SetGridBackgroundImage(int row, int column) { QString pic1Path = QString::fromStdString((*m_games_shared)[itemID].pic_path); const auto blurredPic1Path = Common::FS::GetUserPath(Common::FS::PathType::MetaDataDir) / (*m_games_shared)[itemID].serial / "pic1.png"; -#ifdef _WIN32 - const auto blurredPic1PathQt = QString::fromStdWString(blurredPic1Path.wstring()); -#else - const auto blurredPic1PathQt = QString::fromStdString(blurredPic1Path.string()); -#endif + QString blurredPic1PathQt; + Common::FS::PathToQString(blurredPic1PathQt, blurredPic1Path); backgroundImage = QImage(blurredPic1PathQt); if (backgroundImage.isNull()) { diff --git a/src/qt_gui/game_list_frame.cpp b/src/qt_gui/game_list_frame.cpp index b17da127e..f71728bc3 100644 --- a/src/qt_gui/game_list_frame.cpp +++ b/src/qt_gui/game_list_frame.cpp @@ -2,6 +2,7 @@ // SPDX-License-Identifier: GPL-2.0-or-later #include "common/path_util.h" +#include "common/string_util.h" #include "game_list_frame.h" GameListFrame::GameListFrame(std::shared_ptr game_info_get, QWidget* parent) @@ -92,11 +93,8 @@ void GameListFrame::SetListBackgroundImage(QTableWidgetItem* item) { QString pic1Path = QString::fromStdString(m_game_info->m_games[item->row()].pic_path); const auto blurredPic1Path = Common::FS::GetUserPath(Common::FS::PathType::MetaDataDir) / m_game_info->m_games[item->row()].serial / "pic1.png"; -#ifdef _WIN32 - const auto blurredPic1PathQt = QString::fromStdWString(blurredPic1Path.wstring()); -#else - const auto blurredPic1PathQt = QString::fromStdString(blurredPic1Path.string()); -#endif + QString blurredPic1PathQt; + Common::FS::PathToQString(blurredPic1PathQt, blurredPic1Path); backgroundImage = QImage(blurredPic1PathQt); if (backgroundImage.isNull()) { diff --git a/src/qt_gui/main_window.cpp b/src/qt_gui/main_window.cpp index c60360665..e63e5c25a 100644 --- a/src/qt_gui/main_window.cpp +++ b/src/qt_gui/main_window.cpp @@ -631,7 +631,9 @@ void MainWindow::InstallDragDropPkg(std::filesystem::path file, int pkgNum, int std::string failreason; auto extract_path = std::filesystem::path(Config::getGameInstallDir()) / pkg.GetTitleID(); QString pkgType = QString::fromStdString(pkg.GetPkgFlags()); - QDir game_dir(QString::fromStdString(extract_path.string())); + QString gameDirPath; + Common::FS::PathToQString(gameDirPath, extract_path); + QDir game_dir(gameDirPath); if (game_dir.exists()) { QMessageBox msgBox; msgBox.setWindowTitle(tr("PKG Extraction")); @@ -653,7 +655,9 @@ void MainWindow::InstallDragDropPkg(std::filesystem::path file, int pkgNum, int auto addon_extract_path = Common::FS::GetUserPath(Common::FS::PathType::AddonsDir) / pkg.GetTitleID() / entitlement_label; - QDir addon_dir(QString::fromStdString(addon_extract_path.string())); + QString addonDirPath; + Common::FS::PathToQString(addonDirPath, addon_extract_path); + QDir addon_dir(addonDirPath); auto category = psf.GetString("CATEGORY"); if (pkgType.contains("PATCH")) { @@ -718,8 +722,7 @@ void MainWindow::InstallDragDropPkg(std::filesystem::path file, int pkgNum, int return; } } else { - msgBox.setText(QString(tr("DLC already installed:") + "\n" + - QString::fromStdString(addon_extract_path.string()) + + msgBox.setText(QString(tr("DLC already installed:") + "\n" + addonDirPath + "\n\n" + tr("Would you like to overwrite?"))); msgBox.setStandardButtons(QMessageBox::Yes | QMessageBox::No); msgBox.setDefaultButton(QMessageBox::No); @@ -731,8 +734,7 @@ void MainWindow::InstallDragDropPkg(std::filesystem::path file, int pkgNum, int } } } else { - msgBox.setText(QString(tr("Game already installed") + "\n" + - QString::fromStdString(extract_path.string()) + "\n" + + msgBox.setText(QString(tr("Game already installed") + "\n" + addonDirPath + "\n" + tr("Would you like to overwrite?"))); msgBox.setStandardButtons(QMessageBox::Yes | QMessageBox::No); msgBox.setDefaultButton(QMessageBox::No); diff --git a/src/qt_gui/trophy_viewer.cpp b/src/qt_gui/trophy_viewer.cpp index 8b96948cb..528beee0d 100644 --- a/src/qt_gui/trophy_viewer.cpp +++ b/src/qt_gui/trophy_viewer.cpp @@ -21,15 +21,10 @@ TrophyViewer::TrophyViewer(QString trophyPath, QString gameTrpPath) : QMainWindo } void TrophyViewer::PopulateTrophyWidget(QString title) { -#ifdef _WIN32 const auto trophyDir = Common::FS::GetUserPath(Common::FS::PathType::MetaDataDir) / - title.toStdWString() / "TrophyFiles"; - const auto trophyDirQt = QString::fromStdWString(trophyDir.wstring()); -#else - const auto trophyDir = Common::FS::GetUserPath(Common::FS::PathType::MetaDataDir) / - title.toStdString() / "TrophyFiles"; - const auto trophyDirQt = QString::fromStdString(trophyDir.string()); -#endif + Common::FS::PathFromQString(title) / "TrophyFiles"; + QString trophyDirQt; + Common::FS::PathToQString(trophyDirQt, trophyDir); QDir dir(trophyDirQt); if (!dir.exists()) {