Use fs::path::native whenever possible, avoid unnecessary fs->string conversions in GUI code (#1064)

* Use filesystem::path whenever possible, remove fs::path::string

* My hatred for Windows grows with every passing day

* More Qt stuff

* custom u8string formatter for fmt library

* Use u8string for imgui

* Fix toml errors hopefully

* Fix not printing issue

* Oh and on SDL

* I hate Windows even more today

* fix toml reading utf-8 paths

also small fix for fmt::UTF

* Formatting

* Fix QT path to run games

* Fix path logging in save data

* Fix trophy path handling

* Update game_list_frame.cpp

fixed snd0path

* Update main_window.cpp

fix snd0path

* Update main_window.cpp

* paths finally fixed

* git info in WIP versions title

---------

Co-authored-by: Vinicius Rangel <me@viniciusrangel.dev>
Co-authored-by: georgemoralis <giorgosmrls@gmail.com>
This commit is contained in:
Paris Oplopoios 2024-09-26 11:41:59 +03:00 committed by GitHub
parent 54e2179337
commit 6295d6c416
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
30 changed files with 271 additions and 125 deletions

View file

@ -4,9 +4,25 @@
#include <fstream> #include <fstream>
#include <string> #include <string>
#include <fmt/core.h> #include <fmt/core.h>
#include <fmt/xchar.h> // for wstring support
#include <toml.hpp> #include <toml.hpp>
#include "common/logging/formatter.h"
#include "config.h" #include "config.h"
namespace toml {
template <typename TC, typename K>
std::filesystem::path find_fs_path_or(const basic_value<TC>& v, const K& ky,
std::filesystem::path opt) {
try {
auto str = find<std::string>(v, ky);
std::u8string u8str{(char8_t*)&str.front(), (char8_t*)&str.back() + 1};
return std::filesystem::path{u8str};
} catch (...) {
return opt;
}
}
} // namespace toml
namespace Config { namespace Config {
static bool isNeo = false; static bool isNeo = false;
@ -37,7 +53,7 @@ static bool vkMarkers = false;
static bool vkCrashDiagnostic = false; static bool vkCrashDiagnostic = false;
// Gui // Gui
std::string settings_install_dir = ""; std::filesystem::path settings_install_dir = {};
u32 main_window_geometry_x = 400; u32 main_window_geometry_x = 400;
u32 main_window_geometry_y = 400; u32 main_window_geometry_y = 400;
u32 main_window_geometry_w = 1280; u32 main_window_geometry_w = 1280;
@ -267,7 +283,7 @@ void setMainWindowGeometry(u32 x, u32 y, u32 w, u32 h) {
main_window_geometry_w = w; main_window_geometry_w = w;
main_window_geometry_h = h; main_window_geometry_h = h;
} }
void setGameInstallDir(const std::string& dir) { void setGameInstallDir(const std::filesystem::path& dir) {
settings_install_dir = dir; settings_install_dir = dir;
} }
void setMainWindowTheme(u32 theme) { void setMainWindowTheme(u32 theme) {
@ -323,7 +339,7 @@ u32 getMainWindowGeometryW() {
u32 getMainWindowGeometryH() { u32 getMainWindowGeometryH() {
return main_window_geometry_h; return main_window_geometry_h;
} }
std::string getGameInstallDir() { std::filesystem::path getGameInstallDir() {
return settings_install_dir; return settings_install_dir;
} }
u32 getMainWindowTheme() { u32 getMainWindowTheme() {
@ -378,7 +394,10 @@ void load(const std::filesystem::path& path) {
toml::value data; toml::value data;
try { try {
data = toml::parse(path); std::ifstream ifs;
ifs.exceptions(std::ifstream::failbit | std::ifstream::badbit);
ifs.open(path, std::ios_base::binary);
data = toml::parse(ifs, std::string{fmt::UTF(path.filename().u8string()).data});
} catch (std::exception& ex) { } catch (std::exception& ex) {
fmt::print("Got exception trying to load config file. Exception: {}\n", ex.what()); fmt::print("Got exception trying to load config file. Exception: {}\n", ex.what());
return; return;
@ -444,7 +463,7 @@ void load(const std::filesystem::path& path) {
mw_themes = toml::find_or<int>(gui, "theme", 0); mw_themes = toml::find_or<int>(gui, "theme", 0);
m_window_size_W = toml::find_or<int>(gui, "mw_width", 0); m_window_size_W = toml::find_or<int>(gui, "mw_width", 0);
m_window_size_H = toml::find_or<int>(gui, "mw_height", 0); m_window_size_H = toml::find_or<int>(gui, "mw_height", 0);
settings_install_dir = toml::find_or<std::string>(gui, "installDir", ""); settings_install_dir = toml::find_fs_path_or(gui, "installDir", {});
main_window_geometry_x = toml::find_or<int>(gui, "geometry_x", 0); main_window_geometry_x = toml::find_or<int>(gui, "geometry_x", 0);
main_window_geometry_y = toml::find_or<int>(gui, "geometry_y", 0); main_window_geometry_y = toml::find_or<int>(gui, "geometry_y", 0);
main_window_geometry_w = toml::find_or<int>(gui, "geometry_w", 0); main_window_geometry_w = toml::find_or<int>(gui, "geometry_w", 0);
@ -468,17 +487,19 @@ void save(const std::filesystem::path& path) {
std::error_code error; std::error_code error;
if (std::filesystem::exists(path, error)) { if (std::filesystem::exists(path, error)) {
try { try {
data = toml::parse(path); std::ifstream ifs;
ifs.exceptions(std::ifstream::failbit | std::ifstream::badbit);
ifs.open(path, std::ios_base::binary);
data = toml::parse(ifs, std::string{fmt::UTF(path.filename().u8string()).data});
} catch (const std::exception& ex) { } catch (const std::exception& ex) {
fmt::print("Exception trying to parse config file. Exception: {}\n", ex.what()); fmt::print("Exception trying to parse config file. Exception: {}\n", ex.what());
return; return;
} }
} else { } else {
if (error) { if (error) {
fmt::print("Filesystem error accessing {} (error: {})\n", path.string(), fmt::print("Filesystem error: {}\n", error.message());
error.message().c_str());
} }
fmt::print("Saving new configuration file {}\n", path.string()); fmt::print("Saving new configuration file {}\n", fmt::UTF(path.u8string()));
} }
data["General"]["isPS4Pro"] = isNeo; data["General"]["isPS4Pro"] = isNeo;
@ -515,7 +536,7 @@ void save(const std::filesystem::path& path) {
data["GUI"]["gameTableMode"] = m_table_mode; data["GUI"]["gameTableMode"] = m_table_mode;
data["GUI"]["mw_width"] = m_window_size_W; data["GUI"]["mw_width"] = m_window_size_W;
data["GUI"]["mw_height"] = m_window_size_H; data["GUI"]["mw_height"] = m_window_size_H;
data["GUI"]["installDir"] = settings_install_dir; data["GUI"]["installDir"] = std::string{fmt::UTF(settings_install_dir.u8string()).data};
data["GUI"]["geometry_x"] = main_window_geometry_x; data["GUI"]["geometry_x"] = main_window_geometry_x;
data["GUI"]["geometry_y"] = main_window_geometry_y; data["GUI"]["geometry_y"] = main_window_geometry_y;
data["GUI"]["geometry_w"] = main_window_geometry_w; data["GUI"]["geometry_w"] = main_window_geometry_w;

View file

@ -72,7 +72,7 @@ bool vkCrashDiagnosticEnabled();
// Gui // Gui
void setMainWindowGeometry(u32 x, u32 y, u32 w, u32 h); void setMainWindowGeometry(u32 x, u32 y, u32 w, u32 h);
void setGameInstallDir(const std::string& dir); void setGameInstallDir(const std::filesystem::path& dir);
void setMainWindowTheme(u32 theme); void setMainWindowTheme(u32 theme);
void setIconSize(u32 size); void setIconSize(u32 size);
void setIconSizeGrid(u32 size); void setIconSizeGrid(u32 size);
@ -90,7 +90,7 @@ u32 getMainWindowGeometryX();
u32 getMainWindowGeometryY(); u32 getMainWindowGeometryY();
u32 getMainWindowGeometryW(); u32 getMainWindowGeometryW();
u32 getMainWindowGeometryH(); u32 getMainWindowGeometryH();
std::string getGameInstallDir(); std::filesystem::path getGameInstallDir();
u32 getMainWindowTheme(); u32 getMainWindowTheme();
u32 getIconSize(); u32 getIconSize();
u32 getIconSizeGrid(); u32 getIconSizeGrid();

View file

@ -19,3 +19,24 @@ struct fmt::formatter<T, std::enable_if_t<std::is_enum_v<T>, char>>
} }
}; };
#endif #endif
namespace fmt {
template <typename T = std::string_view>
struct UTF {
T data;
explicit UTF(const std::u8string_view view) {
data = T{(const char*)&view.front(), (const char*)&view.back() + 1};
}
explicit UTF(const std::u8string& str) : UTF(std::u8string_view{str}) {}
};
} // namespace fmt
template <>
struct fmt::formatter<fmt::UTF<std::string_view>, char> : formatter<std::string_view> {
template <typename FormatContext>
auto format(const UTF<std::string_view>& wrapper, FormatContext& ctx) const {
return formatter<std::string_view>::format(wrapper.data, ctx);
}
};

View file

@ -119,9 +119,9 @@ std::string convertValueToHex(const std::string type, const std::string valueStr
void OnGameLoaded() { void OnGameLoaded() {
if (!patchFile.empty()) { 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_document doc;
pugi::xml_parse_result result = doc.load_file(filePath.c_str()); pugi::xml_parse_result result = doc.load_file(filePath.c_str());
@ -187,8 +187,8 @@ void OnGameLoaded() {
#ifdef ENABLE_QT_GUI #ifdef ENABLE_QT_GUI
// We use the QT headers for the xml and json parsing, this define is only true on QT builds // We use the QT headers for the xml and json parsing, this define is only true on QT builds
QString patchDir = QString patchDir;
QString::fromStdString(Common::FS::GetUserPath(Common::FS::PathType::PatchesDir).string()); Common::FS::PathToQString(patchDir, Common::FS::GetUserPath(Common::FS::PathType::PatchesDir));
QString repositories[] = {"GoldHEN", "shadPS4"}; QString repositories[] = {"GoldHEN", "shadPS4"};
for (const QString& repository : repositories) { for (const QString& repository : repositories) {

View file

@ -22,6 +22,10 @@
#endif #endif
#endif #endif
#ifdef ENABLE_QT_GUI
#include <QString>
#endif
namespace Common::FS { namespace Common::FS {
namespace fs = std::filesystem; 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); 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 } // namespace Common::FS

View file

@ -6,6 +6,10 @@
#include <filesystem> #include <filesystem>
#include <vector> #include <vector>
#ifdef ENABLE_QT_GUI
class QString; // to avoid including <QString> in this header
#endif
namespace Common::FS { namespace Common::FS {
enum class PathType { 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); 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 } // namespace Common::FS

View file

@ -371,8 +371,7 @@ bool PKG::Extract(const std::filesystem::path& filepath, const std::filesystem::
if (table.type == PFS_CURRENT_DIR) { if (table.type == PFS_CURRENT_DIR) {
current_dir = extractPaths[table.inode]; current_dir = extractPaths[table.inode];
} }
extractPaths[table.inode] = extractPaths[table.inode] = current_dir / std::filesystem::path(table.name);
current_dir.string() / std::filesystem::path(table.name);
if (table.type == PFS_FILE || table.type == PFS_DIR) { if (table.type == PFS_FILE || table.type == PFS_DIR) {
if (table.type == PFS_DIR) { // Create dirs. if (table.type == PFS_DIR) { // Create dirs.
@ -402,7 +401,7 @@ void PKG::ExtractFiles(const int index) {
int bsize = iNodeBuf[inode_number].Size; int bsize = iNodeBuf[inode_number].Size;
Common::FS::IOFile inflated; 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. Common::FS::IOFile pkgFile; // Open the file for each iteration to avoid conflict.
pkgFile.Open(pkgpath, Common::FS::FileAccessMode::Read); pkgFile.Open(pkgpath, Common::FS::FileAccessMode::Read);

View file

@ -12,8 +12,8 @@
#define STBI_NO_STDIO #define STBI_NO_STDIO
#include "externals/stb_image.h" #include "externals/stb_image.h"
bool Splash::Open(const std::string& filepath) { bool Splash::Open(const std::filesystem::path& filepath) {
ASSERT_MSG(filepath.ends_with(".png"), "Unexpected file format passed"); ASSERT_MSG(filepath.stem().string() != "png", "Unexpected file format passed");
Common::FS::IOFile file(filepath, Common::FS::FileAccessMode::Read); Common::FS::IOFile file(filepath, Common::FS::FileAccessMode::Read);
if (!file.IsOpen()) { if (!file.IsOpen()) {

View file

@ -3,6 +3,7 @@
#pragma once #pragma once
#include <filesystem>
#include <string> #include <string>
#include <vector> #include <vector>
#include "common/types.h" #include "common/types.h"
@ -22,7 +23,7 @@ public:
Splash() = default; Splash() = default;
~Splash() = default; ~Splash() = default;
bool Open(const std::string& filepath); bool Open(const std::filesystem::path& filepath);
[[nodiscard]] bool IsLoaded() const { [[nodiscard]] bool IsLoaded() const {
return img_data.size(); return img_data.size();
} }

View file

@ -29,7 +29,7 @@ static void removePadding(std::vector<u8>& vec) {
} }
bool TRP::Extract(const std::filesystem::path& trophyPath) { 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/"; std::filesystem::path gameSysDir = trophyPath / "sce_sys/trophy/";
if (!std::filesystem::exists(gameSysDir)) { if (!std::filesystem::exists(gameSysDir)) {
return false; return false;

View file

@ -557,10 +557,10 @@ s32 PS4_SYSV_ABI sceNpTrophyGetTrophyUnlockState(OrbisNpTrophyContext context,
const auto trophyDir = const auto trophyDir =
Common::FS::GetUserPath(Common::FS::PathType::MetaDataDir) / game_serial / "TrophyFiles"; Common::FS::GetUserPath(Common::FS::PathType::MetaDataDir) / game_serial / "TrophyFiles";
auto trophy_file = trophyDir / "trophy00" / "Xml" / "TROP.XML";
pugi::xml_document doc; pugi::xml_document doc;
pugi::xml_parse_result result = pugi::xml_parse_result result = doc.load_file(trophy_file.native().c_str());
doc.load_file((trophyDir.string() + "/trophy00/Xml/TROP.XML").c_str());
int numTrophies = 0; int numTrophies = 0;

View file

@ -107,14 +107,16 @@ static void BackupThreadBody() {
} }
g_backup_status = WorkerStatus::Running; g_backup_status = WorkerStatus::Running;
LOG_INFO(Lib_SaveData, "Backing up the following directory: {}", req.save_path.string()); LOG_INFO(Lib_SaveData, "Backing up the following directory: {}",
fmt::UTF(req.save_path.u8string()));
try { try {
backup(req.save_path); backup(req.save_path);
} catch (const std::filesystem::filesystem_error& err) { } catch (const std::filesystem::filesystem_error& err) {
LOG_ERROR(Lib_SaveData, "Failed to backup {}: {}", req.save_path.string(), err.what()); LOG_ERROR(Lib_SaveData, "Failed to backup {}: {}", fmt::UTF(req.save_path.u8string()),
err.what());
} }
LOG_DEBUG(Lib_SaveData, "Backing up the following directory: {} finished", LOG_DEBUG(Lib_SaveData, "Backing up the following directory: {} finished",
req.save_path.string()); fmt::UTF(req.save_path.u8string()));
{ {
std::scoped_lock lk{g_backup_queue_mutex}; std::scoped_lock lk{g_backup_queue_mutex};
g_backup_queue.front().done = true; g_backup_queue.front().done = true;
@ -160,7 +162,7 @@ bool NewRequest(OrbisUserServiceUserId user_id, std::string_view title_id,
if (g_backup_status != WorkerStatus::Waiting && g_backup_status != WorkerStatus::Running) { if (g_backup_status != WorkerStatus::Waiting && g_backup_status != WorkerStatus::Running) {
LOG_ERROR(Lib_SaveData, "Called backup while status is {}. Backup request to {} ignored", LOG_ERROR(Lib_SaveData, "Called backup while status is {}. Backup request to {} ignored",
magic_enum::enum_name(g_backup_status.load()), save_path.string()); magic_enum::enum_name(g_backup_status.load()), fmt::UTF(save_path.u8string()));
return false; return false;
} }
{ {
@ -184,7 +186,7 @@ bool NewRequest(OrbisUserServiceUserId user_id, std::string_view title_id,
} }
bool Restore(const std::filesystem::path& save_path) { bool Restore(const std::filesystem::path& save_path) {
LOG_INFO(Lib_SaveData, "Restoring backup for {}", save_path.string()); LOG_INFO(Lib_SaveData, "Restoring backup for {}", fmt::UTF(save_path.u8string()));
std::unique_lock lk{g_backup_running_mutex}; std::unique_lock lk{g_backup_running_mutex};
if (!fs::exists(save_path) || !fs::exists(save_path / backup_dir)) { if (!fs::exists(save_path) || !fs::exists(save_path / backup_dir)) {
return false; return false;

View file

@ -77,7 +77,7 @@ static void SaveFileSafe(void* buf, size_t count, const std::filesystem::path& p
g_saving_memory = true; g_saving_memory = true;
std::scoped_lock lk{g_saving_memory_mutex}; std::scoped_lock lk{g_saving_memory_mutex};
try { try {
LOG_DEBUG(Lib_SaveData, "Saving save data memory {}", g_save_path.string()); LOG_DEBUG(Lib_SaveData, "Saving save data memory {}", fmt::UTF(g_save_path.u8string()));
if (g_memory_dirty) { if (g_memory_dirty) {
g_memory_dirty = false; g_memory_dirty = false;
@ -163,7 +163,8 @@ size_t CreateSaveMemory(size_t memory_size) {
bool ok = g_param_sfo.Open(g_param_sfo_path); bool ok = g_param_sfo.Open(g_param_sfo_path);
if (!ok) { if (!ok) {
LOG_ERROR(Lib_SaveData, "Failed to open SFO at {}", g_param_sfo_path.string()); LOG_ERROR(Lib_SaveData, "Failed to open SFO at {}",
fmt::UTF(g_param_sfo_path.u8string()));
throw std::filesystem::filesystem_error( throw std::filesystem::filesystem_error(
"failed to open SFO", g_param_sfo_path, "failed to open SFO", g_param_sfo_path,
std::make_error_code(std::errc::illegal_byte_sequence)); std::make_error_code(std::errc::illegal_byte_sequence));

View file

@ -607,7 +607,7 @@ Error PS4_SYSV_ABI sceSaveDataCheckBackupData(const OrbisSaveDataCheckBackupData
if (check->param != nullptr) { if (check->param != nullptr) {
PSF sfo; PSF sfo;
if (!sfo.Open(backup_path / "sce_sys" / "param.sfo")) { if (!sfo.Open(backup_path / "sce_sys" / "param.sfo")) {
LOG_ERROR(Lib_SaveData, "Failed to read SFO at {}", backup_path.string()); LOG_ERROR(Lib_SaveData, "Failed to read SFO at {}", fmt::UTF(backup_path.u8string()));
return Error::INTERNAL; return Error::INTERNAL;
} }
check->param->FromSFO(sfo); check->param->FromSFO(sfo);
@ -818,7 +818,7 @@ Error PS4_SYSV_ABI sceSaveDataDirNameSearch(const OrbisSaveDataDirNameSearchCond
const auto sfo_path = SaveInstance::GetParamSFOPath(dir_path); const auto sfo_path = SaveInstance::GetParamSFOPath(dir_path);
PSF sfo; PSF sfo;
if (!sfo.Open(sfo_path)) { if (!sfo.Open(sfo_path)) {
LOG_ERROR(Lib_SaveData, "Failed to read SFO: {}", sfo_path.string()); LOG_ERROR(Lib_SaveData, "Failed to read SFO: {}", fmt::UTF(sfo_path.u8string()));
ASSERT_MSG(false, "Failed to read SFO"); ASSERT_MSG(false, "Failed to read SFO");
} }
map_dir_sfo.emplace(dir_name, std::move(sfo)); map_dir_sfo.emplace(dir_name, std::move(sfo));

View file

@ -139,7 +139,7 @@ void Emulator::Run(const std::filesystem::path& file) {
if (splash->IsLoaded()) { if (splash->IsLoaded()) {
continue; continue;
} }
if (!splash->Open(entry.path().string())) { if (!splash->Open(entry.path())) {
LOG_ERROR(Loader, "Game splash: unable to open file"); LOG_ERROR(Loader, "Game splash: unable to open file");
} }
} }
@ -189,7 +189,7 @@ void Emulator::Run(const std::filesystem::path& file) {
if (!std::filesystem::exists(mount_captures_dir)) { if (!std::filesystem::exists(mount_captures_dir)) {
std::filesystem::create_directory(mount_captures_dir); std::filesystem::create_directory(mount_captures_dir);
} }
VideoCore::SetOutputDir(mount_captures_dir.generic_string(), id); VideoCore::SetOutputDir(mount_captures_dir, id);
// Initialize kernel and library facilities. // Initialize kernel and library facilities.
Libraries::Kernel::init_pthreads(); Libraries::Kernel::init_pthreads();
@ -205,7 +205,7 @@ void Emulator::Run(const std::filesystem::path& file) {
std::filesystem::path sce_module_folder = file.parent_path() / "sce_module"; std::filesystem::path sce_module_folder = file.parent_path() / "sce_module";
if (std::filesystem::is_directory(sce_module_folder)) { if (std::filesystem::is_directory(sce_module_folder)) {
for (const auto& entry : std::filesystem::directory_iterator(sce_module_folder)) { for (const auto& entry : std::filesystem::directory_iterator(sce_module_folder)) {
LOG_INFO(Loader, "Loading {}", entry.path().string().c_str()); LOG_INFO(Loader, "Loading {}", fmt::UTF(entry.path().u8string()));
linker->LoadModule(entry.path()); linker->LoadModule(entry.path());
} }
} }

View file

@ -51,8 +51,16 @@ void Initialize(const ::Vulkan::Instance& instance, const Frontend::WindowSDL& w
io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad; io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad;
io.ConfigFlags |= ImGuiConfigFlags_DockingEnable; io.ConfigFlags |= ImGuiConfigFlags_DockingEnable;
io.DisplaySize = ImVec2((float)window.getWidth(), (float)window.getHeight()); 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()); auto path = config_path.u8string();
char* config_file_buf = new char[path.size() + 1]();
std::memcpy(config_file_buf, path.c_str(), path.size());
io.IniFilename = config_file_buf;
path = log_path.u8string();
char* log_file_buf = new char[path.size() + 1]();
std::memcpy(log_file_buf, path.c_str(), path.size());
io.LogFilename = log_file_buf;
ImFontGlyphRangesBuilder rb{}; ImFontGlyphRangesBuilder rb{};
rb.AddRanges(io.Fonts->GetGlyphRangesDefault()); rb.AddRanges(io.Fonts->GetGlyphRangesDefault());
@ -114,8 +122,8 @@ void Shutdown(const vk::Device& device) {
Sdl::Shutdown(); Sdl::Shutdown();
DestroyContext(); DestroyContext();
SDL_free(ini_filename); delete[] (char*)ini_filename;
SDL_free(log_filename); delete[] (char*)log_filename;
} }
bool ProcessEvent(SDL_Event* event) { bool ProcessEvent(SDL_Event* event) {

View file

@ -5,7 +5,15 @@
#include "common/memory_patcher.h" #include "common/memory_patcher.h"
#include "emulator.h" #include "emulator.h"
#ifdef _WIN32
#include <windows.h>
#endif
int main(int argc, char* argv[]) { int main(int argc, char* argv[]) {
#ifdef _WIN32
SetConsoleOutputCP(CP_UTF8);
#endif
if (argc == 1) { if (argc == 1) {
fmt::print("Usage: {} <elf or eboot.bin path>\n", argv[0]); fmt::print("Usage: {} <elf or eboot.bin path>\n", argv[0]);
return -1; return -1;

View file

@ -50,8 +50,9 @@ void CheatsPatches::setupUI() {
defaultTextEdit = tr("defaultTextEdit_MSG"); defaultTextEdit = tr("defaultTextEdit_MSG");
defaultTextEdit.replace("\\n", "\n"); defaultTextEdit.replace("\\n", "\n");
QString CHEATS_DIR_QString = QString CHEATS_DIR_QString;
QString::fromStdString(Common::FS::GetUserPath(Common::FS::PathType::CheatsDir).string()); Common::FS::PathToQString(CHEATS_DIR_QString,
Common::FS::GetUserPath(Common::FS::PathType::CheatsDir));
QString NameCheatJson = m_gameSerial + "_" + m_gameVersion + ".json"; QString NameCheatJson = m_gameSerial + "_" + m_gameVersion + ".json";
m_cheatFilePath = CHEATS_DIR_QString + "/" + NameCheatJson; m_cheatFilePath = CHEATS_DIR_QString + "/" + NameCheatJson;
@ -275,9 +276,9 @@ void CheatsPatches::onSaveButtonClicked() {
int separatorIndex = selectedPatchName.indexOf(" | "); int separatorIndex = selectedPatchName.indexOf(" | ");
selectedPatchName = selectedPatchName.mid(separatorIndex + 3); selectedPatchName = selectedPatchName.mid(separatorIndex + 3);
QString patchDir = QString patchDir;
QString::fromStdString(Common::FS::GetUserPath(Common::FS::PathType::PatchesDir).string()) + Common::FS::PathToQString(patchDir, Common::FS::GetUserPath(Common::FS::PathType::PatchesDir));
"/" + selectedPatchName; patchDir += "/" + selectedPatchName;
QString filesJsonPath = patchDir + "/files.json"; QString filesJsonPath = patchDir + "/files.json";
QFile jsonFile(filesJsonPath); QFile jsonFile(filesJsonPath);
@ -555,10 +556,10 @@ void CheatsPatches::downloadCheats(const QString& source, const QString& gameSer
if (dotIndex != -1) { if (dotIndex != -1) {
baseFileName.insert(dotIndex, "_wolf2022"); baseFileName.insert(dotIndex, "_wolf2022");
} }
QString filePath = QString filePath;
QString::fromStdString( Common::FS::PathToQString(filePath,
Common::FS::GetUserPath(Common::FS::PathType::CheatsDir).string()) + Common::FS::GetUserPath(Common::FS::PathType::CheatsDir));
"/" + baseFileName; filePath += "/" + baseFileName;
if (QFile::exists(filePath) && showMessageBox) { if (QFile::exists(filePath) && showMessageBox) {
QMessageBox::StandardButton reply2; QMessageBox::StandardButton reply2;
reply2 = reply2 =
@ -612,8 +613,9 @@ void CheatsPatches::populateFileListPatches() {
} }
m_patchInfos.clear(); m_patchInfos.clear();
QString patchesDir = QString patchesDir;
QString::fromStdString(Common::FS::GetUserPath(Common::FS::PathType::PatchesDir).string()); Common::FS::PathToQString(patchesDir,
Common::FS::GetUserPath(Common::FS::PathType::PatchesDir));
QDir dir(patchesDir); QDir dir(patchesDir);
QStringList folders = dir.entryList(QDir::Dirs | QDir::NoDotAndDotDot); QStringList folders = dir.entryList(QDir::Dirs | QDir::NoDotAndDotDot);
@ -906,8 +908,8 @@ void CheatsPatches::addCheatsToLayout(const QJsonArray& modsArray, const QJsonAr
} }
void CheatsPatches::populateFileListCheats() { void CheatsPatches::populateFileListCheats() {
QString cheatsDir = QString cheatsDir;
QString::fromStdString(Common::FS::GetUserPath(Common::FS::PathType::CheatsDir).string()); Common::FS::PathToQString(cheatsDir, Common::FS::GetUserPath(Common::FS::PathType::CheatsDir));
QString pattern = m_gameSerial + "_" + m_gameVersion + "*.json"; QString pattern = m_gameSerial + "_" + m_gameVersion + "*.json";
QDir dir(cheatsDir); QDir dir(cheatsDir);
@ -932,8 +934,9 @@ void CheatsPatches::populateFileListCheats() {
if (!selectedIndexes.isEmpty()) { if (!selectedIndexes.isEmpty()) {
QString selectedFileName = selectedIndexes.first().data().toString(); QString selectedFileName = selectedIndexes.first().data().toString();
QString cheatsDir = QString::fromStdString( QString cheatsDir;
Common::FS::GetUserPath(Common::FS::PathType::CheatsDir).string()); Common::FS::PathToQString(
cheatsDir, Common::FS::GetUserPath(Common::FS::PathType::CheatsDir));
QFile file(cheatsDir + "/" + selectedFileName); QFile file(cheatsDir + "/" + selectedFileName);
if (file.open(QIODevice::ReadOnly)) { if (file.open(QIODevice::ReadOnly)) {

View file

@ -44,7 +44,8 @@ void GameGridFrame::PlayBackgroundMusic(QTableWidgetItem* item) {
BackgroundMusicPlayer::getInstance().stopMusic(); BackgroundMusicPlayer::getInstance().stopMusic();
return; return;
} }
const auto snd0path = QString::fromStdString(m_game_info->m_games[item->row()].snd0_path); QString snd0path;
Common::FS::PathToQString(snd0path, m_game_info->m_games[item->row()].snd0_path);
BackgroundMusicPlayer::getInstance().playMusic(snd0path); BackgroundMusicPlayer::getInstance().playMusic(snd0path);
} }
@ -122,14 +123,12 @@ void GameGridFrame::SetGridBackgroundImage(int row, int column) {
int itemID = (row * this->columnCount()) + column; int itemID = (row * this->columnCount()) + column;
QWidget* item = this->cellWidget(row, column); QWidget* item = this->cellWidget(row, column);
if (item) { if (item) {
QString pic1Path = QString::fromStdString((*m_games_shared)[itemID].pic_path); QString pic1Path;
Common::FS::PathToQString(pic1Path, (*m_games_shared)[itemID].pic_path);
const auto blurredPic1Path = Common::FS::GetUserPath(Common::FS::PathType::MetaDataDir) / const auto blurredPic1Path = Common::FS::GetUserPath(Common::FS::PathType::MetaDataDir) /
(*m_games_shared)[itemID].serial / "pic1.png"; (*m_games_shared)[itemID].serial / "pic1.png";
#ifdef _WIN32 QString blurredPic1PathQt;
const auto blurredPic1PathQt = QString::fromStdWString(blurredPic1Path.wstring()); Common::FS::PathToQString(blurredPic1PathQt, blurredPic1Path);
#else
const auto blurredPic1PathQt = QString::fromStdString(blurredPic1Path.string());
#endif
backgroundImage = QImage(blurredPic1PathQt); backgroundImage = QImage(blurredPic1PathQt);
if (backgroundImage.isNull()) { if (backgroundImage.isNull()) {

View file

@ -3,13 +3,15 @@
#include <QProgressDialog> #include <QProgressDialog>
#include "common/path_util.h"
#include "game_info.h" #include "game_info.h"
GameInfoClass::GameInfoClass() = default; GameInfoClass::GameInfoClass() = default;
GameInfoClass::~GameInfoClass() = default; GameInfoClass::~GameInfoClass() = default;
void GameInfoClass::GetGameInfo(QWidget* parent) { void GameInfoClass::GetGameInfo(QWidget* parent) {
QString installDir = QString::fromStdString(Config::getGameInstallDir()); QString installDir;
Common::FS::PathToQString(installDir, Config::getGameInstallDir());
QStringList filePaths; QStringList filePaths;
QDir parentFolder(installDir); QDir parentFolder(installDir);
QFileInfoList fileList = parentFolder.entryInfoList(QDir::Dirs | QDir::NoDotAndDotDot); QFileInfoList fileList = parentFolder.entryInfoList(QDir::Dirs | QDir::NoDotAndDotDot);
@ -19,7 +21,7 @@ void GameInfoClass::GetGameInfo(QWidget* parent) {
} }
} }
m_games = QtConcurrent::mapped(filePaths, [&](const QString& path) { m_games = QtConcurrent::mapped(filePaths, [&](const QString& path) {
return readGameInfo(path.toStdString()); return readGameInfo(Common::FS::PathFromQString(path));
}).results(); }).results();
// Progress bar, please be patient :) // Progress bar, please be patient :)

View file

@ -22,17 +22,19 @@ public:
return a.name < b.name; return a.name < b.name;
} }
static GameInfo readGameInfo(const std::string& filePath) { static GameInfo readGameInfo(const std::filesystem::path& filePath) {
GameInfo game; GameInfo game;
game.path = filePath; game.path = filePath;
PSF psf; PSF psf;
if (psf.Open(std::filesystem::path(game.path) / "sce_sys" / "param.sfo")) { if (psf.Open(game.path / "sce_sys" / "param.sfo")) {
game.icon_path = game.path + "/sce_sys/icon0.png"; game.icon_path = game.path / "sce_sys" / "icon0.png";
QString iconpath = QString::fromStdString(game.icon_path); QString iconpath;
Common::FS::PathToQString(iconpath, game.icon_path);
game.icon = QImage(iconpath); game.icon = QImage(iconpath);
game.pic_path = game.path + "/sce_sys/pic1.png"; game.pic_path = game.path / "sce_sys" / "pic1.png";
game.snd0_path = game.path + "/sce_sys/snd0.at9"; game.snd0_path = game.path / "sce_sys" / "snd0.at9";
if (const auto title = psf.GetString("TITLE"); title.has_value()) { if (const auto title = psf.GetString("TITLE"); title.has_value()) {
game.name = *title; game.name = *title;
} }

View file

@ -41,7 +41,9 @@ QWidget* GameInstallDialog::SetupGamesDirectory() {
// Input. // Input.
m_gamesDirectory = new QLineEdit(); m_gamesDirectory = new QLineEdit();
m_gamesDirectory->setText(QString::fromStdString(Config::getGameInstallDir())); QString install_dir;
Common::FS::PathToQString(install_dir, Config::getGameInstallDir());
m_gamesDirectory->setText(install_dir);
m_gamesDirectory->setMinimumWidth(400); m_gamesDirectory->setMinimumWidth(400);
layout->addWidget(m_gamesDirectory); layout->addWidget(m_gamesDirectory);
@ -76,7 +78,7 @@ void GameInstallDialog::Save() {
return; return;
} }
Config::setGameInstallDir(gamesDirectory.toStdString()); Config::setGameInstallDir(Common::FS::PathFromQString(gamesDirectory));
const auto config_dir = Common::FS::GetUserPath(Common::FS::PathType::UserDir); const auto config_dir = Common::FS::GetUserPath(Common::FS::PathType::UserDir);
Config::save(config_dir / "config.toml"); Config::save(config_dir / "config.toml");
accept(); accept();

View file

@ -2,6 +2,7 @@
// SPDX-License-Identifier: GPL-2.0-or-later // SPDX-License-Identifier: GPL-2.0-or-later
#include "common/path_util.h" #include "common/path_util.h"
#include "common/string_util.h"
#include "game_list_frame.h" #include "game_list_frame.h"
GameListFrame::GameListFrame(std::shared_ptr<GameInfoClass> game_info_get, QWidget* parent) GameListFrame::GameListFrame(std::shared_ptr<GameInfoClass> game_info_get, QWidget* parent)
@ -73,7 +74,8 @@ void GameListFrame::PlayBackgroundMusic(QTableWidgetItem* item) {
BackgroundMusicPlayer::getInstance().stopMusic(); BackgroundMusicPlayer::getInstance().stopMusic();
return; return;
} }
const auto snd0path = QString::fromStdString(m_game_info->m_games[item->row()].snd0_path); QString snd0path;
Common::FS::PathToQString(snd0path, m_game_info->m_games[item->row()].snd0_path);
BackgroundMusicPlayer::getInstance().playMusic(snd0path); BackgroundMusicPlayer::getInstance().playMusic(snd0path);
} }
@ -88,7 +90,9 @@ void GameListFrame::PopulateGameList() {
SetTableItem(i, 4, QString::fromStdString(m_game_info->m_games[i].fw)); SetTableItem(i, 4, QString::fromStdString(m_game_info->m_games[i].fw));
SetTableItem(i, 5, QString::fromStdString(m_game_info->m_games[i].size)); SetTableItem(i, 5, QString::fromStdString(m_game_info->m_games[i].size));
SetTableItem(i, 6, QString::fromStdString(m_game_info->m_games[i].version)); SetTableItem(i, 6, QString::fromStdString(m_game_info->m_games[i].version));
SetTableItem(i, 7, QString::fromStdString(m_game_info->m_games[i].path)); QString path;
Common::FS::PathToQString(path, m_game_info->m_games[i].path);
SetTableItem(i, 7, path);
} }
} }
@ -98,14 +102,12 @@ void GameListFrame::SetListBackgroundImage(QTableWidgetItem* item) {
return; return;
} }
QString pic1Path = QString::fromStdString(m_game_info->m_games[item->row()].pic_path); QString pic1Path;
Common::FS::PathToQString(pic1Path, m_game_info->m_games[item->row()].pic_path);
const auto blurredPic1Path = Common::FS::GetUserPath(Common::FS::PathType::MetaDataDir) / const auto blurredPic1Path = Common::FS::GetUserPath(Common::FS::PathType::MetaDataDir) /
m_game_info->m_games[item->row()].serial / "pic1.png"; m_game_info->m_games[item->row()].serial / "pic1.png";
#ifdef _WIN32 QString blurredPic1PathQt;
const auto blurredPic1PathQt = QString::fromStdWString(blurredPic1Path.wstring()); Common::FS::PathToQString(blurredPic1PathQt, blurredPic1Path);
#else
const auto blurredPic1PathQt = QString::fromStdString(blurredPic1Path.string());
#endif
backgroundImage = QImage(blurredPic1PathQt); backgroundImage = QImage(blurredPic1PathQt);
if (backgroundImage.isNull()) { if (backgroundImage.isNull()) {

View file

@ -3,11 +3,14 @@
#pragma once #pragma once
#include "common/path_util.h"
struct GameInfo { struct GameInfo {
std::string path; // root path of game directory (normally directory that contains eboot.bin) std::filesystem::path path; // root path of game directory
std::string icon_path; // path of icon0.png // (normally directory that contains eboot.bin)
std::string pic_path; // path of pic1.png std::filesystem::path icon_path; // path of icon0.png
std::string snd0_path; // path of snd0.at9 std::filesystem::path pic_path; // path of pic1.png
std::filesystem::path snd0_path; // path of snd0.at9
QImage icon; QImage icon;
std::string size; std::string size;
// variables extracted from param.sfo // variables extracted from param.sfo
@ -44,7 +47,9 @@ public:
} }
static void GetFolderSize(GameInfo& game) { static void GetFolderSize(GameInfo& game) {
QDir dir(QString::fromStdString(game.path)); QString dirPath;
Common::FS::PathToQString(dirPath, game.path);
QDir dir(dirPath);
QDirIterator it(dir.absolutePath(), QDirIterator::Subdirectories); QDirIterator it(dir.absolutePath(), QDirIterator::Subdirectories);
qint64 total = 0; qint64 total = 0;
while (it.hasNext()) { while (it.hasNext()) {

View file

@ -75,7 +75,8 @@ public:
} }
if (selected == &openFolder) { if (selected == &openFolder) {
QString folderPath = QString::fromStdString(m_games[itemID].path); QString folderPath;
Common::FS::PathToQString(folderPath, m_games[itemID].path);
QDesktopServices::openUrl(QUrl::fromLocalFile(folderPath)); QDesktopServices::openUrl(QUrl::fromLocalFile(folderPath));
} }
@ -158,7 +159,9 @@ public:
QString gameSerial = QString::fromStdString(m_games[itemID].serial); QString gameSerial = QString::fromStdString(m_games[itemID].serial);
QString gameVersion = QString::fromStdString(m_games[itemID].version); QString gameVersion = QString::fromStdString(m_games[itemID].version);
QString gameSize = QString::fromStdString(m_games[itemID].size); QString gameSize = QString::fromStdString(m_games[itemID].size);
QPixmap gameImage(QString::fromStdString(m_games[itemID].icon_path)); QString iconPath;
Common::FS::PathToQString(iconPath, m_games[itemID].icon_path);
QPixmap gameImage(iconPath);
CheatsPatches* cheatsPatches = CheatsPatches* cheatsPatches =
new CheatsPatches(gameName, gameSerial, gameVersion, gameSize, gameImage); new CheatsPatches(gameName, gameSerial, gameVersion, gameSize, gameImage);
cheatsPatches->show(); cheatsPatches->show();
@ -167,8 +170,9 @@ public:
} }
if (selected == &openTrophyViewer) { if (selected == &openTrophyViewer) {
QString trophyPath = QString::fromStdString(m_games[itemID].serial); QString trophyPath, gameTrpPath;
QString gameTrpPath = QString::fromStdString(m_games[itemID].path); Common::FS::PathToQString(trophyPath, m_games[itemID].serial);
Common::FS::PathToQString(gameTrpPath, m_games[itemID].path);
TrophyViewer* trophyViewer = new TrophyViewer(trophyPath, gameTrpPath); TrophyViewer* trophyViewer = new TrophyViewer(trophyPath, gameTrpPath);
trophyViewer->show(); trophyViewer->show();
connect(widget->parent(), &QWidget::destroyed, trophyViewer, connect(widget->parent(), &QWidget::destroyed, trophyViewer,
@ -176,11 +180,13 @@ public:
} }
if (selected == &createShortcut) { if (selected == &createShortcut) {
QString targetPath = QString::fromStdString(m_games[itemID].path); QString targetPath;
Common::FS::PathToQString(targetPath, m_games[itemID].path);
QString ebootPath = targetPath + "/eboot.bin"; QString ebootPath = targetPath + "/eboot.bin";
// Get the full path to the icon // Get the full path to the icon
QString iconPath = QString::fromStdString(m_games[itemID].icon_path); QString iconPath;
Common::FS::PathToQString(iconPath, m_games[itemID].icon_path);
QFileInfo iconFileInfo(iconPath); QFileInfo iconFileInfo(iconPath);
QString icoPath = iconFileInfo.absolutePath() + "/" + iconFileInfo.baseName() + ".ico"; QString icoPath = iconFileInfo.absolutePath() + "/" + iconFileInfo.baseName() + ".ico";

View file

@ -8,10 +8,18 @@
#include "game_install_dialog.h" #include "game_install_dialog.h"
#include "main_window.h" #include "main_window.h"
#ifdef _WIN32
#include <windows.h>
#endif
// Custom message handler to ignore Qt logs // Custom message handler to ignore Qt logs
void customMessageHandler(QtMsgType, const QMessageLogContext&, const QString&) {} void customMessageHandler(QtMsgType, const QMessageLogContext&, const QString&) {}
int main(int argc, char* argv[]) { int main(int argc, char* argv[]) {
#ifdef _WIN32
SetConsoleOutputCP(CP_UTF8);
#endif
QApplication a(argc, argv); QApplication a(argc, argv);
// Load configurations and initialize Qt application // Load configurations and initialize Qt application
@ -22,7 +30,7 @@ int main(int argc, char* argv[]) {
bool has_command_line_argument = argc > 1; bool has_command_line_argument = argc > 1;
// Check if the game install directory is set // Check if the game install directory is set
if (Config::getGameInstallDir() == "" && !has_command_line_argument) { if (Config::getGameInstallDir().empty() && !has_command_line_argument) {
GameInstallDialog dlg; GameInstallDialog dlg;
dlg.exec(); dlg.exec();
} }

View file

@ -4,10 +4,12 @@
#include <QDockWidget> #include <QDockWidget>
#include <QProgressDialog> #include <QProgressDialog>
#include <common/scm_rev.h>
#include "about_dialog.h" #include "about_dialog.h"
#include "cheats_patches.h" #include "cheats_patches.h"
#include "check_update.h" #include "check_update.h"
#include "common/io_file.h" #include "common/io_file.h"
#include "common/path_util.h"
#include "common/string_util.h" #include "common/string_util.h"
#include "common/version.h" #include "common/version.h"
#include "core/file_format/pkg.h" #include "core/file_format/pkg.h"
@ -43,7 +45,14 @@ bool MainWindow::Init() {
GetPhysicalDevices(); GetPhysicalDevices();
// show ui // show ui
setMinimumSize(350, minimumSizeHint().height()); setMinimumSize(350, minimumSizeHint().height());
setWindowTitle(QString::fromStdString("shadPS4 v" + std::string(Common::VERSION))); std::string window_title = "";
if (Common::isRelease) {
window_title = fmt::format("shadPS4 v{}", Common::VERSION);
} else {
window_title = fmt::format("shadPS4 v{} {} {}", Common::VERSION, Common::g_scm_branch,
Common::g_scm_desc);
}
setWindowTitle(QString::fromStdString(window_title));
this->show(); this->show();
// load game list // load game list
LoadGameLists(); LoadGameLists();
@ -433,12 +442,14 @@ void MainWindow::CreateConnects() {
.arg(" APP VERSION", -11) .arg(" APP VERSION", -11)
.arg(" Path"); .arg(" Path");
for (const GameInfo& game : m_game_info->m_games) { for (const GameInfo& game : m_game_info->m_games) {
QString game_path;
Common::FS::PathToQString(game_path, game.path);
out << QString("%1 %2 %3 %4 %5\n") out << QString("%1 %2 %3 %4 %5\n")
.arg(QString::fromStdString(game.name), -50) .arg(QString::fromStdString(game.name), -50)
.arg(QString::fromStdString(game.serial), -10) .arg(QString::fromStdString(game.serial), -10)
.arg(QString::fromStdString(game.fw), -4) .arg(QString::fromStdString(game.fw), -4)
.arg(QString::fromStdString(game.version), -11) .arg(QString::fromStdString(game.version), -11)
.arg(QString::fromStdString(game.path)); .arg(game_path);
} }
}); });
@ -517,7 +528,8 @@ void MainWindow::PlayBackgroundMusic() {
: m_game_grid_frame->crtRow * m_game_grid_frame->columnCnt + : m_game_grid_frame->crtRow * m_game_grid_frame->columnCnt +
m_game_grid_frame->crtColumn; m_game_grid_frame->crtColumn;
const auto snd0path = QString::fromStdString(m_game_info->m_games[itemID].snd0_path); QString snd0path;
Common::FS::PathToQString(snd0path, m_game_info->m_games[itemID].snd0_path);
BackgroundMusicPlayer::getInstance().playMusic(snd0path); BackgroundMusicPlayer::getInstance().playMusic(snd0path);
} }
@ -529,28 +541,29 @@ void MainWindow::StartGame() {
if (table_mode == 0) { if (table_mode == 0) {
if (m_game_list_frame->currentItem()) { if (m_game_list_frame->currentItem()) {
int itemID = m_game_list_frame->currentItem()->row(); int itemID = m_game_list_frame->currentItem()->row();
gamePath = QString::fromStdString(m_game_info->m_games[itemID].path + "/eboot.bin"); Common::FS::PathToQString(gamePath, m_game_info->m_games[itemID].path / "eboot.bin");
} }
} else if (table_mode == 1) { } else if (table_mode == 1) {
if (m_game_grid_frame->cellClicked) { if (m_game_grid_frame->cellClicked) {
int itemID = (m_game_grid_frame->crtRow * m_game_grid_frame->columnCnt) + int itemID = (m_game_grid_frame->crtRow * m_game_grid_frame->columnCnt) +
m_game_grid_frame->crtColumn; m_game_grid_frame->crtColumn;
gamePath = QString::fromStdString(m_game_info->m_games[itemID].path + "/eboot.bin"); Common::FS::PathToQString(gamePath, m_game_info->m_games[itemID].path / "eboot.bin");
} }
} else { } else {
if (m_elf_viewer->currentItem()) { if (m_elf_viewer->currentItem()) {
int itemID = m_elf_viewer->currentItem()->row(); int itemID = m_elf_viewer->currentItem()->row();
gamePath = QString::fromStdString(m_elf_viewer->m_elf_list[itemID].toStdString()); gamePath = m_elf_viewer->m_elf_list[itemID];
} }
} }
if (gamePath != "") { if (gamePath != "") {
AddRecentFiles(gamePath); AddRecentFiles(gamePath);
Core::Emulator emulator; Core::Emulator emulator;
if (!std::filesystem::exists(gamePath.toUtf8().constData())) { const auto path = Common::FS::PathFromQString(gamePath);
if (!std::filesystem::exists(path)) {
QMessageBox::critical(nullptr, tr("Run Game"), QString(tr("Eboot.bin file not found"))); QMessageBox::critical(nullptr, tr("Run Game"), QString(tr("Eboot.bin file not found")));
return; return;
} }
emulator.Run(gamePath.toUtf8().constData()); emulator.Run(path);
} }
} }
@ -666,9 +679,11 @@ void MainWindow::InstallDragDropPkg(std::filesystem::path file, int pkgNum, int
pkg = PKG(); pkg = PKG();
pkg.Open(file); pkg.Open(file);
std::string failreason; std::string failreason;
auto extract_path = std::filesystem::path(Config::getGameInstallDir()) / pkg.GetTitleID(); auto extract_path = Config::getGameInstallDir() / pkg.GetTitleID();
QString pkgType = QString::fromStdString(pkg.GetPkgFlags()); 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()) { if (game_dir.exists()) {
QMessageBox msgBox; QMessageBox msgBox;
msgBox.setWindowTitle(tr("PKG Extraction")); msgBox.setWindowTitle(tr("PKG Extraction"));
@ -690,7 +705,9 @@ void MainWindow::InstallDragDropPkg(std::filesystem::path file, int pkgNum, int
auto addon_extract_path = Common::FS::GetUserPath(Common::FS::PathType::AddonsDir) / auto addon_extract_path = Common::FS::GetUserPath(Common::FS::PathType::AddonsDir) /
pkg.GetTitleID() / entitlement_label; 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"); auto category = psf.GetString("CATEGORY");
if (pkgType.contains("PATCH")) { if (pkgType.contains("PATCH")) {
@ -755,8 +772,7 @@ void MainWindow::InstallDragDropPkg(std::filesystem::path file, int pkgNum, int
return; return;
} }
} else { } else {
msgBox.setText(QString(tr("DLC already installed:") + "\n" + msgBox.setText(QString(tr("DLC already installed:") + "\n" + addonDirPath +
QString::fromStdString(addon_extract_path.string()) +
"\n\n" + tr("Would you like to overwrite?"))); "\n\n" + tr("Would you like to overwrite?")));
msgBox.setStandardButtons(QMessageBox::Yes | QMessageBox::No); msgBox.setStandardButtons(QMessageBox::Yes | QMessageBox::No);
msgBox.setDefaultButton(QMessageBox::No); msgBox.setDefaultButton(QMessageBox::No);
@ -768,8 +784,7 @@ void MainWindow::InstallDragDropPkg(std::filesystem::path file, int pkgNum, int
} }
} }
} else { } else {
msgBox.setText(QString(tr("Game already installed") + "\n" + msgBox.setText(QString(tr("Game already installed") + "\n" + addonDirPath + "\n" +
QString::fromStdString(extract_path.string()) + "\n" +
tr("Would you like to overwrite?"))); tr("Would you like to overwrite?")));
msgBox.setStandardButtons(QMessageBox::Yes | QMessageBox::No); msgBox.setStandardButtons(QMessageBox::Yes | QMessageBox::No);
msgBox.setDefaultButton(QMessageBox::No); msgBox.setDefaultButton(QMessageBox::No);
@ -812,7 +827,8 @@ void MainWindow::InstallDragDropPkg(std::filesystem::path file, int pkgNum, int
QFutureWatcher<void> futureWatcher; QFutureWatcher<void> futureWatcher;
connect(&futureWatcher, &QFutureWatcher<void>::finished, this, [=, this]() { connect(&futureWatcher, &QFutureWatcher<void>::finished, this, [=, this]() {
if (pkgNum == nPkg) { if (pkgNum == nPkg) {
QString path = QString::fromStdString(Config::getGameInstallDir()); QString path;
Common::FS::PathToQString(path, Config::getGameInstallDir());
QMessageBox extractMsgBox(this); QMessageBox extractMsgBox(this);
extractMsgBox.setWindowTitle(tr("Extraction Finished")); extractMsgBox.setWindowTitle(tr("Extraction Finished"));
extractMsgBox.setText( extractMsgBox.setText(
@ -984,14 +1000,14 @@ void MainWindow::CreateRecentGameActions() {
} }
connect(m_recent_files_group, &QActionGroup::triggered, this, [this](QAction* action) { connect(m_recent_files_group, &QActionGroup::triggered, this, [this](QAction* action) {
QString gamePath = action->text(); auto gamePath = Common::FS::PathFromQString(action->text());
AddRecentFiles(gamePath); // Update the list. AddRecentFiles(action->text()); // Update the list.
Core::Emulator emulator; Core::Emulator emulator;
if (!std::filesystem::exists(gamePath.toUtf8().constData())) { if (!std::filesystem::exists(gamePath)) {
QMessageBox::critical(nullptr, tr("Run Game"), QString(tr("Eboot.bin file not found"))); QMessageBox::critical(nullptr, tr("Run Game"), QString(tr("Eboot.bin file not found")));
return; return;
} }
emulator.Run(gamePath.toUtf8().constData()); emulator.Run(gamePath);
}); });
} }

View file

@ -21,15 +21,10 @@ TrophyViewer::TrophyViewer(QString trophyPath, QString gameTrpPath) : QMainWindo
} }
void TrophyViewer::PopulateTrophyWidget(QString title) { void TrophyViewer::PopulateTrophyWidget(QString title) {
#ifdef _WIN32
const auto trophyDir = Common::FS::GetUserPath(Common::FS::PathType::MetaDataDir) / const auto trophyDir = Common::FS::GetUserPath(Common::FS::PathType::MetaDataDir) /
title.toStdWString() / "TrophyFiles"; Common::FS::PathFromQString(title) / "TrophyFiles";
const auto trophyDirQt = QString::fromStdWString(trophyDir.wstring()); QString trophyDirQt;
#else Common::FS::PathToQString(trophyDirQt, trophyDir);
const auto trophyDir = Common::FS::GetUserPath(Common::FS::PathType::MetaDataDir) /
title.toStdString() / "TrophyFiles";
const auto trophyDirQt = QString::fromStdString(trophyDir.string());
#endif
QDir dir(trophyDirQt); QDir dir(trophyDirQt);
if (!dir.exists()) { if (!dir.exists()) {

View file

@ -110,11 +110,11 @@ void TriggerCapture() {
} }
} }
void SetOutputDir(const std::string& path, const std::string& prefix) { void SetOutputDir(const std::filesystem::path& path, const std::string& prefix) {
if (!rdoc_api) { if (!rdoc_api) {
return; return;
} }
rdoc_api->SetCaptureFilePathTemplate((path + '\\' + prefix).c_str()); rdoc_api->SetCaptureFilePathTemplate(fmt::UTF((path / prefix).u8string()).data.data());
} }
} // namespace VideoCore } // namespace VideoCore

View file

@ -20,6 +20,6 @@ void EndCapture();
void TriggerCapture(); void TriggerCapture();
/// Sets output directory for captures /// Sets output directory for captures
void SetOutputDir(const std::string& path, const std::string& prefix); void SetOutputDir(const std::filesystem::path& path, const std::string& prefix);
} // namespace VideoCore } // namespace VideoCore