Ditch fs::get_executable_dir

This commit is contained in:
Nekotekina 2017-02-22 16:08:53 +03:00
parent 4cba60b27f
commit baf22527b0
12 changed files with 73 additions and 137 deletions

View file

@ -1125,11 +1125,22 @@ const std::string& fs::get_config_dir()
// Use magic static // Use magic static
static const std::string s_dir = [] static const std::string s_dir = []
{ {
#ifdef _WIN32
return get_executable_dir(); // ?
#else
std::string dir; std::string dir;
#ifdef _WIN32
wchar_t buf[2048];
if (GetModuleFileName(NULL, buf, ::size32(buf)) - 1 >= ::size32(buf) - 1)
{
MessageBoxA(0, fmt::format("GetModuleFileName() failed: error %u.", GetLastError()).c_str(), "fs::get_config_dir()", MB_ICONERROR);
return dir; // empty
}
to_utf8(dir, buf); // Convert to UTF-8
std::replace(dir.begin(), dir.end(), '\\', '/');
dir.resize(dir.rfind('/') + 1);
#else
if (const char* home = ::getenv("XDG_CONFIG_HOME")) if (const char* home = ::getenv("XDG_CONFIG_HOME"))
dir = home; dir = home;
else if (const char* home = ::getenv("HOME")) else if (const char* home = ::getenv("HOME"))
@ -1142,59 +1153,9 @@ const std::string& fs::get_config_dir()
if (!is_dir(dir) && !create_path(dir)) if (!is_dir(dir) && !create_path(dir))
{ {
std::printf("Failed to create configuration directory '%s' (%d).\n", dir.c_str(), errno); std::printf("Failed to create configuration directory '%s' (%d).\n", dir.c_str(), errno);
return get_executable_dir();
} }
return dir;
#endif #endif
}();
return s_dir;
}
const std::string& fs::get_executable_dir()
{
// Use magic static
static const std::string s_dir = []
{
std::string dir;
#ifdef _WIN32
wchar_t buf[2048];
if (GetModuleFileName(NULL, buf, ::size32(buf)) - 1 >= ::size32(buf) - 1)
{
MessageBoxA(0, fmt::format("GetModuleFileName() failed: error %u.", GetLastError()).c_str(), "fs::get_executable_dir()", MB_ICONERROR);
return dir; // empty
}
to_utf8(dir, buf); // Convert to UTF-8
std::replace(dir.begin(), dir.end(), '\\', '/');
#elif __APPLE__
char buf[4096];
u32 size = sizeof(buf);
if (_NSGetExecutablePath(buf, &size))
{
std::printf("_NSGetExecutablePath() failed (size=0x%x).\n", size);
return dir; // empty
}
dir = buf;
#else
char buf[4096];
const auto size = ::readlink("/proc/self/exe", buf, sizeof(buf));
if (size <= 0 || size >= sizeof(buf))
{
std::printf("readlink(/proc/self/exe) failed (%d).\n", errno);
return dir; // empty
}
dir.assign(buf, size);
#endif
// Leave only path
dir.resize(dir.rfind('/') + 1);
return dir; return dir;
}(); }();

View file

@ -444,9 +444,6 @@ namespace fs
// Get configuration directory // Get configuration directory
const std::string& get_config_dir(); const std::string& get_config_dir();
// Get executable directory
const std::string& get_executable_dir();
// Get data/cache directory for specified prefix and suffix // Get data/cache directory for specified prefix and suffix
std::string get_data_dir(const std::string& prefix, const std::string& location, const std::string& suffix); std::string get_data_dir(const std::string& prefix, const std::string& location, const std::string& suffix);

View file

@ -38,11 +38,6 @@ namespace rsx
{ {
std::function<bool(u32 addr, bool is_writing)> g_access_violation_handler; std::function<bool(u32 addr, bool is_writing)> g_access_violation_handler;
std::string old_shaders_cache::shaders_cache::path_to_root()
{
return fs::get_executable_dir() + "data/";
}
void old_shaders_cache::shaders_cache::load(const std::string &path, shader_language lang) void old_shaders_cache::shaders_cache::load(const std::string &path, shader_language lang)
{ {
const std::string lang_name(lang == shader_language::glsl ? "glsl" : "hlsl"); const std::string lang_name(lang == shader_language::glsl ? "glsl" : "hlsl");
@ -65,7 +60,6 @@ namespace rsx
} }
catch (...) catch (...)
{ {
LOG_WARNING(RSX, "Cache file '%s' ignored", entry.name);
continue; continue;
} }
@ -87,17 +81,7 @@ namespace rsx
void old_shaders_cache::shaders_cache::load(shader_language lang) void old_shaders_cache::shaders_cache::load(shader_language lang)
{ {
std::string root = path_to_root(); load(Emu.GetCachePath(), lang);
//shared cache
load(root + "cache/", lang);
std::string title_id = Emu.GetTitleID();
if (!title_id.empty())
{
load(root + title_id + "/cache/", lang);
}
} }
u32 get_address(u32 offset, u32 location) u32 get_address(u32 offset, u32 location)

View file

@ -99,8 +99,6 @@ namespace rsx
void load(const std::string &path, shader_language lang); void load(const std::string &path, shader_language lang);
void load(shader_language lang); void load(shader_language lang);
static std::string path_to_root();
}; };
} }

View file

@ -90,23 +90,8 @@ namespace rsx
programs_cache::programs_cache() programs_cache::programs_cache()
{ {
std::string path{ fs::get_executable_dir() + "data/cache/" }; m_vertex_shaders_cache.path(Emu.GetCachePath());
std::string title = Emu.GetTitleID(); m_fragment_shader_cache.path(Emu.GetCachePath());
if (title.empty())
{
path += "temporary/";
fs::remove_all(path, false);
}
else
{
path += title + "/";
}
fs::create_path(path);
m_vertex_shaders_cache.path(path);
m_fragment_shader_cache.path(path);
} }
programs_cache::~programs_cache() programs_cache::~programs_cache()

View file

@ -30,7 +30,7 @@ system_type g_system;
cfg::bool_entry g_cfg_autostart(cfg::root.misc, "Always start after boot", true); cfg::bool_entry g_cfg_autostart(cfg::root.misc, "Always start after boot", true);
cfg::bool_entry g_cfg_autoexit(cfg::root.misc, "Exit RPCS3 when process finishes"); cfg::bool_entry g_cfg_autoexit(cfg::root.misc, "Exit RPCS3 when process finishes");
cfg::string_entry g_cfg_vfs_emulator_dir(cfg::root.vfs, "$(EmulatorDir)"); // Default (empty): taken from fs::get_executable_dir() cfg::string_entry g_cfg_vfs_emulator_dir(cfg::root.vfs, "$(EmulatorDir)"); // Default (empty): taken from fs::get_config_dir()
cfg::string_entry g_cfg_vfs_dev_hdd0(cfg::root.vfs, "/dev_hdd0/", "$(EmulatorDir)dev_hdd0/"); cfg::string_entry g_cfg_vfs_dev_hdd0(cfg::root.vfs, "/dev_hdd0/", "$(EmulatorDir)dev_hdd0/");
cfg::string_entry g_cfg_vfs_dev_hdd1(cfg::root.vfs, "/dev_hdd1/", "$(EmulatorDir)dev_hdd1/"); cfg::string_entry g_cfg_vfs_dev_hdd1(cfg::root.vfs, "/dev_hdd1/", "$(EmulatorDir)dev_hdd1/");
cfg::string_entry g_cfg_vfs_dev_flash(cfg::root.vfs, "/dev_flash/", "$(EmulatorDir)dev_flash/"); cfg::string_entry g_cfg_vfs_dev_flash(cfg::root.vfs, "/dev_flash/", "$(EmulatorDir)dev_flash/");
@ -131,7 +131,7 @@ bool Emulator::BootGame(const std::string& path, bool direct)
std::string Emulator::GetGameDir() std::string Emulator::GetGameDir()
{ {
const std::string& emu_dir_ = g_cfg_vfs_emulator_dir; const std::string& emu_dir_ = g_cfg_vfs_emulator_dir;
const std::string& emu_dir = emu_dir_.empty() ? fs::get_executable_dir() : emu_dir_; const std::string& emu_dir = emu_dir_.empty() ? fs::get_config_dir() : emu_dir_;
return fmt::replace_all(g_cfg_vfs_dev_hdd0, "$(EmulatorDir)", emu_dir) + "game/"; return fmt::replace_all(g_cfg_vfs_dev_hdd0, "$(EmulatorDir)", emu_dir) + "game/";
} }
@ -139,7 +139,7 @@ std::string Emulator::GetGameDir()
std::string Emulator::GetLibDir() std::string Emulator::GetLibDir()
{ {
const std::string& emu_dir_ = g_cfg_vfs_emulator_dir; const std::string& emu_dir_ = g_cfg_vfs_emulator_dir;
const std::string& emu_dir = emu_dir_.empty() ? fs::get_executable_dir() : emu_dir_; const std::string& emu_dir = emu_dir_.empty() ? fs::get_config_dir() : emu_dir_;
return fmt::replace_all(g_cfg_vfs_dev_flash, "$(EmulatorDir)", emu_dir) + "sys/external/"; return fmt::replace_all(g_cfg_vfs_dev_flash, "$(EmulatorDir)", emu_dir) + "sys/external/";
} }
@ -173,12 +173,12 @@ void Emulator::Load()
m_title_id = psf::get_string(_psf, "TITLE_ID"); m_title_id = psf::get_string(_psf, "TITLE_ID");
// Initialize data/cache directory // Initialize data/cache directory
const std::string data_dir = fs::get_data_dir(m_title_id, m_path); m_cache_path = fs::get_data_dir(m_title_id, m_path);
// Check SELF header // Check SELF header
if (elf_file.size() >= 4 && elf_file.read<u32>() == "SCE\0"_u32) if (elf_file.size() >= 4 && elf_file.read<u32>() == "SCE\0"_u32)
{ {
const std::string decrypted_path = data_dir + "boot.elf"; const std::string decrypted_path = m_cache_path + "boot.elf";
fs::stat_t encrypted_stat = elf_file.stat(); fs::stat_t encrypted_stat = elf_file.stat();
fs::stat_t decrypted_stat; fs::stat_t decrypted_stat;
@ -201,13 +201,13 @@ void Emulator::Load()
} }
else else
{ {
LOG_ERROR(LOADER, "Failed to create boot.elf", data_dir); LOG_ERROR(LOADER, "Failed to create boot.elf");
} }
} }
} }
// Load custom config-1 // Load custom config-1
if (fs::file cfg_file{data_dir + "config.yml"}) if (fs::file cfg_file{m_cache_path + "config.yml"})
{ {
LOG_NOTICE(LOADER, "Applying custom config (config.yml)"); LOG_NOTICE(LOADER, "Applying custom config (config.yml)");
cfg::root.from_string(cfg_file.to_string()); cfg::root.from_string(cfg_file.to_string());
@ -248,7 +248,7 @@ void Emulator::Load()
// Mount all devices // Mount all devices
const std::string& emu_dir_ = g_cfg_vfs_emulator_dir; const std::string& emu_dir_ = g_cfg_vfs_emulator_dir;
const std::string& emu_dir = emu_dir_.empty() ? fs::get_executable_dir() : emu_dir_; const std::string& emu_dir = emu_dir_.empty() ? fs::get_config_dir() : emu_dir_;
const std::string& bdvd_dir = g_cfg_vfs_dev_bdvd; const std::string& bdvd_dir = g_cfg_vfs_dev_bdvd;
const std::string& home_dir = g_cfg_vfs_app_home; const std::string& home_dir = g_cfg_vfs_app_home;

View file

@ -50,6 +50,7 @@ class Emulator final
std::string m_path; std::string m_path;
std::string m_elf_path; std::string m_elf_path;
std::string m_cache_path;
std::string m_title_id; std::string m_title_id;
std::string m_title; std::string m_title;
@ -98,6 +99,11 @@ public:
return m_title; return m_title;
} }
const std::string& GetCachePath() const
{
return m_cache_path;
}
u64 GetPauseTime() u64 GetPauseTime()
{ {
return m_pause_amend_time; return m_pause_amend_time;

View file

@ -234,13 +234,10 @@ void MainFrame::BootGame(wxCommandEvent& WXUNUSED(event))
void MainFrame::InstallPkg(wxCommandEvent& WXUNUSED(event)) void MainFrame::InstallPkg(wxCommandEvent& WXUNUSED(event))
{ {
const bool paused = Emu.Pause();
wxFileDialog ctrl(this, L"Select PKG", wxEmptyString, wxEmptyString, "PKG files (*.pkg)|*.pkg|All files (*.*)|*.*", wxFD_OPEN | wxFD_FILE_MUST_EXIST); wxFileDialog ctrl(this, L"Select PKG", wxEmptyString, wxEmptyString, "PKG files (*.pkg)|*.pkg|All files (*.*)|*.*", wxFD_OPEN | wxFD_FILE_MUST_EXIST);
if (ctrl.ShowModal() == wxID_CANCEL) if (ctrl.ShowModal() == wxID_CANCEL)
{ {
if (paused) Emu.Resume();
return; return;
} }
@ -372,6 +369,8 @@ void MainFrame::DecryptSPRXLibraries(wxCommandEvent& WXUNUSED(event))
return; return;
} }
Emu.Stop();
wxArrayString modules; wxArrayString modules;
ctrl.GetPaths(modules); ctrl.GetPaths(modules);
@ -427,9 +426,12 @@ void MainFrame::InstallFirmware(wxCommandEvent& WXUNUSED(event))
return; return;
} }
Emu.Stop();
fs::file pup_f(ctrl.GetPath().ToStdString()); fs::file pup_f(ctrl.GetPath().ToStdString());
pup_object pup(pup_f); pup_object pup(pup_f);
if (!pup) { if (!pup)
{
LOG_ERROR(GENERAL, "Error while installing firmware: PUP file is invalid."); LOG_ERROR(GENERAL, "Error while installing firmware: PUP file is invalid.");
wxMessageBox("Error while installing firmware: PUP file is invalid.", "Failure!", wxOK | wxICON_ERROR, this); wxMessageBox("Error while installing firmware: PUP file is invalid.", "Failure!", wxOK | wxICON_ERROR, this);
return; return;
@ -440,7 +442,7 @@ void MainFrame::InstallFirmware(wxCommandEvent& WXUNUSED(event))
auto updatefilenames = update_files.get_filenames(); auto updatefilenames = update_files.get_filenames();
updatefilenames.erase(std::remove_if( updatefilenames.erase(std::remove_if(
updatefilenames.begin(), updatefilenames.end(), [](std::string s) {return s.find("dev_flash_") == std::string::npos; }), updatefilenames.begin(), updatefilenames.end(), [](std::string s) { return s.find("dev_flash_") == std::string::npos; }),
updatefilenames.end()); updatefilenames.end());
wxProgressDialog pdlg("Firmware Installer", "Please wait, unpacking...", updatefilenames.size(), this, wxPD_AUTO_HIDE | wxPD_APP_MODAL | wxPD_CAN_ABORT); wxProgressDialog pdlg("Firmware Installer", "Please wait, unpacking...", updatefilenames.size(), this, wxPD_AUTO_HIDE | wxPD_APP_MODAL | wxPD_CAN_ABORT);
@ -470,7 +472,7 @@ void MainFrame::InstallFirmware(wxCommandEvent& WXUNUSED(event))
} }
tar_object dev_flash_tar(dev_flash_tar_f[2]); tar_object dev_flash_tar(dev_flash_tar_f[2]);
if (!dev_flash_tar.extract(fs::get_executable_dir())) if (!dev_flash_tar.extract(fs::get_config_dir()))
{ {
LOG_ERROR(GENERAL, "Error while installing firmware: TAR contents are invalid."); LOG_ERROR(GENERAL, "Error while installing firmware: TAR contents are invalid.");
wxMessageBox("Error while installing firmware: TAR contents are invalid.", "Failure!", wxOK | wxICON_ERROR, this); wxMessageBox("Error while installing firmware: TAR contents are invalid.", "Failure!", wxOK | wxICON_ERROR, this);

View file

@ -6,8 +6,8 @@ pup_object::pup_object(const fs::file& file): m_file(file)
{ {
PUPHeader m_header; PUPHeader m_header;
m_file.read(m_header); m_file.read(m_header);
if (m_header.magic != "SCEUF\0\0\0"_u64) if (m_header.magic != "SCEUF\0\0\0"_u64)
{ {
isValid = false; isValid = false;
return; return;
} }
@ -22,7 +22,7 @@ fs::file pup_object::get_file(u64 entry_id)
{ {
if (!isValid) return fs::file(); if (!isValid) return fs::file();
for (PUPFileEntry file_entry : m_file_tbl) for (PUPFileEntry file_entry : m_file_tbl)
{ {
if (file_entry.entry_id == entry_id) if (file_entry.entry_id == entry_id)
{ {

View file

@ -5,29 +5,33 @@
#include <vector> #include <vector>
typedef struct { struct PUPHeader
{
le_t<u64> magic; le_t<u64> magic;
be_t<u64> package_version; be_t<u64> package_version;
be_t<u64> image_version; be_t<u64> image_version;
be_t<u64> file_count; be_t<u64> file_count;
be_t<u64> header_length; be_t<u64> header_length;
be_t<u64> data_length; be_t<u64> data_length;
} PUPHeader; };
typedef struct { struct PUPFileEntry
{
be_t<u64> entry_id; be_t<u64> entry_id;
be_t<u64> data_offset; be_t<u64> data_offset;
be_t<u64> data_length; be_t<u64> data_length;
u8 padding[8]; u8 padding[8];
} PUPFileEntry; };
typedef struct { struct PUPHashEntry
{
be_t<u64> entry_id; be_t<u64> entry_id;
be_t<u8> hash[20]; u8 hash[20];
be_t<u8> padding[4]; u8 padding[4];
} PUPHashEntry; };
class pup_object { class pup_object
{
const fs::file& m_file; const fs::file& m_file;
bool isValid = true; bool isValid = true;
@ -37,7 +41,7 @@ class pup_object {
public: public:
pup_object(const fs::file& file); pup_object(const fs::file& file);
operator bool() const { return isValid; }; explicit operator bool() const { return isValid; };
fs::file get_file(u64 entry_id); fs::file get_file(u64 entry_id);
}; };

View file

@ -5,7 +5,9 @@
#include <cmath> #include <cmath>
#include <cstdlib> #include <cstdlib>
tar_object::tar_object(const fs::file& file, size_t offset) : m_file(file), initial_offset(offset) tar_object::tar_object(const fs::file& file, size_t offset)
: m_file(file)
, initial_offset(offset)
{ {
m_file.seek(initial_offset); m_file.seek(initial_offset);
largest_offset = initial_offset; largest_offset = initial_offset;
@ -34,8 +36,6 @@ int octalToDecimal(int octalNumber)
std::vector<std::string> tar_object::get_filenames() std::vector<std::string> tar_object::get_filenames()
{ {
if (!isValid) return std::vector<std::string>();
std::vector<std::string> vec; std::vector<std::string> vec;
get_file(""); get_file("");
for (auto it = m_map.cbegin(); it != m_map.cend(); ++it) for (auto it = m_map.cbegin(); it != m_map.cend(); ++it)
@ -47,7 +47,7 @@ std::vector<std::string> tar_object::get_filenames()
fs::file tar_object::get_file(std::string path) fs::file tar_object::get_file(std::string path)
{ {
if (!isValid || !m_file) return fs::file(); if (!m_file) return fs::file();
auto it = m_map.find(path); auto it = m_map.find(path);
if (it != m_map.end()) if (it != m_map.end())
@ -62,9 +62,9 @@ fs::file tar_object::get_file(std::string path)
} }
else //continue scanning from last file entered else //continue scanning from last file entered
{ {
while (m_file.pos() < m_file.size()) { while (m_file.pos() < m_file.size())
{
TARHeader header = read_header(largest_offset); TARHeader header = read_header(largest_offset);
if (!isValid) return fs::file();
if (std::string(header.magic).find("ustar") != std::string::npos) if (std::string(header.magic).find("ustar") != std::string::npos)
m_map[header.name] = largest_offset; m_map[header.name] = largest_offset;
@ -85,7 +85,7 @@ fs::file tar_object::get_file(std::string path)
m_file.seek(offset); m_file.seek(offset);
largest_offset = offset; largest_offset = offset;
} }
} }
return fs::file(); return fs::file();
} }
@ -93,7 +93,7 @@ fs::file tar_object::get_file(std::string path)
bool tar_object::extract(std::string path) bool tar_object::extract(std::string path)
{ {
if (!isValid || !m_file) return false; if (!m_file) return false;
get_file(""); //Make sure we have scanned all files get_file(""); //Make sure we have scanned all files
for (auto iter : m_map) for (auto iter : m_map)
@ -101,7 +101,8 @@ bool tar_object::extract(std::string path)
TARHeader header = read_header(iter.second); TARHeader header = read_header(iter.second);
if (std::string(header.name).empty()) continue; if (std::string(header.name).empty()) continue;
switch (header.filetype) { switch (header.filetype)
{
case '0': case '0':
{ {
fs::file file(header.name, fs::rewrite); fs::file file(header.name, fs::rewrite);
@ -116,9 +117,9 @@ bool tar_object::extract(std::string path)
} }
default: default:
LOG_ERROR(GENERAL,"Tar loader: unknown file type: "+header.filetype); LOG_ERROR(GENERAL,"Tar loader: unknown file type: %c", header.filetype);
return false; return false;
} }
} }
return true; return true;
} }

View file

@ -2,7 +2,8 @@
#include <map> #include <map>
typedef struct { struct TARHeader
{
char name[100]; char name[100];
char dontcare[24]; char dontcare[24];
char size[12]; char size[12];
@ -14,7 +15,7 @@ typedef struct {
char dontcare2[82]; char dontcare2[82];
char prefix[155]; char prefix[155];
char padding[12]; char padding[12];
} TARHeader; };
class tar_object class tar_object
{ {
@ -23,18 +24,15 @@ class tar_object
int initial_offset; int initial_offset;
int largest_offset; //we store the largest offset so we can continue to scan from there. int largest_offset; //we store the largest offset so we can continue to scan from there.
std::map<std::string, u64> m_map; //maps path to offset of header of that file, so we only need to scan the entire file once. std::map<std::string, u64> m_map; //maps path to offset of header of that file, so we only need to scan the entire file once.
bool isValid = true;
TARHeader read_header(u64 offset); TARHeader read_header(u64 offset);
public: public:
tar_object(const fs::file& file, size_t offset = 0); tar_object(const fs::file& file, size_t offset = 0);
operator bool() const { return isValid; };
std::vector<std::string> get_filenames(); std::vector<std::string> get_filenames();
fs::file get_file(std::string path); fs::file get_file(std::string path);
bool extract(std::string path); // extract all files in archive to path bool extract(std::string path); // extract all files in archive to path
}; };