diff --git a/Utilities/File.cpp b/Utilities/File.cpp index 709f8829dd..e2ea1fb2de 100644 --- a/Utilities/File.cpp +++ b/Utilities/File.cpp @@ -1403,8 +1403,8 @@ const std::string& fs::get_config_dir() if (const char* home = ::getenv("HOME")) dir = home + "/Library/Application Support"s; #else - if (const char* home = ::getenv("XDG_CONFIG_HOME")) - dir = home; + if (const char* conf = ::getenv("XDG_CONFIG_HOME")) + dir = conf; else if (const char* home = ::getenv("HOME")) dir = home + "/.config"s; #endif @@ -1425,15 +1425,53 @@ const std::string& fs::get_config_dir() return s_dir; } +const std::string& fs::get_cache_dir() +{ + static const std::string s_dir = [] + { + std::string dir; + +#ifdef _WIN32 + dir = get_config_dir(); +#else + +#ifdef __APPLE__ + if (const char* home = ::getenv("HOME")) + dir = home + "/Library/Caches"s; +#else + if (const char* cache = ::getenv("XDG_CACHE_HOME")) + dir = cache; + else if (const char* conf = ::getenv("XDG_CONFIG_HOME")) + dir = conf; + else if (const char* home = ::getenv("HOME")) + dir = home + "/.cache"s; +#endif + else // Just in case + dir = "./cache"; + + dir += "/rpcs3/"; + + if (!create_path(dir)) + { + std::printf("Failed to create configuration directory '%s' (%d).\n", dir.c_str(), errno); + } +#endif + + return dir; + }(); + + return s_dir; +} + std::string fs::get_data_dir(const std::string& prefix, const std::string& location, const std::string& suffix) { static const std::string s_dir = [] { - const std::string dir = get_config_dir() + "data/"; + const std::string dir = get_cache_dir() + "data/"; if (!create_path(dir)) { - return get_config_dir(); + return get_cache_dir(); } return dir; diff --git a/Utilities/File.h b/Utilities/File.h index f701b56c29..792b7ad22b 100644 --- a/Utilities/File.h +++ b/Utilities/File.h @@ -484,6 +484,9 @@ namespace fs // Get configuration directory const std::string& get_config_dir(); + // Get common cache directory + const std::string& get_cache_dir(); + // 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); diff --git a/Utilities/Log.cpp b/Utilities/Log.cpp index 322277ee8c..47383ef567 100644 --- a/Utilities/Log.cpp +++ b/Utilities/Log.cpp @@ -322,8 +322,8 @@ void logs::message::broadcast(const char* fmt, const fmt_type_info* sup, ...) co logs::file_writer::file_writer(const std::string& name) : m_name(name) { - const std::string log_name = fs::get_config_dir() + name + ".log"; - const std::string buf_name = fs::get_config_dir() + name + ".buf"; + const std::string log_name = fs::get_cache_dir() + name + ".log"; + const std::string buf_name = fs::get_cache_dir() + name + ".buf"; try { @@ -352,7 +352,7 @@ logs::file_writer::file_writer(const std::string& name) // Check free space fs::device_stat stats{}; - if (!fs::statfs(fs::get_config_dir(), stats) || stats.avail_free < s_log_size * 8) + if (!fs::statfs(fs::get_cache_dir(), stats) || stats.avail_free < s_log_size * 8) { fmt::throw_exception("Not enough free space (%f KB)", stats.avail_free / 1000000.); } @@ -372,9 +372,9 @@ logs::file_writer::file_writer(const std::string& name) verify(name.c_str()), m_fptr; // Rotate backups (TODO) - fs::remove_file(fs::get_config_dir() + name + "1.log.gz"); - fs::create_dir(fs::get_config_dir() + "old_logs"); - fs::rename(fs::get_config_dir() + m_name + ".log.gz", fs::get_config_dir() + "old_logs/" + m_name + ".log.gz", true); + fs::remove_file(fs::get_cache_dir() + name + "1.log.gz"); + fs::create_dir(fs::get_cache_dir() + "old_logs"); + fs::rename(fs::get_cache_dir() + m_name + ".log.gz", fs::get_cache_dir() + "old_logs/" + m_name + ".log.gz", true); // Actual log file (allowed to fail) m_fout.open(log_name, fs::rewrite); diff --git a/rpcs3/Emu/Audio/AudioDumper.cpp b/rpcs3/Emu/Audio/AudioDumper.cpp index cceb2d2e0e..f27ac5a9c8 100644 --- a/rpcs3/Emu/Audio/AudioDumper.cpp +++ b/rpcs3/Emu/Audio/AudioDumper.cpp @@ -7,7 +7,7 @@ AudioDumper::AudioDumper(u16 ch) { if (GetCh()) { - m_output.open(fs::get_config_dir() + "audio.wav", fs::rewrite); + m_output.open(fs::get_cache_dir() + "audio.wav", fs::rewrite); m_output.write(m_header); // write initial file header } } diff --git a/rpcs3/Emu/Cell/PPUThread.cpp b/rpcs3/Emu/Cell/PPUThread.cpp index a76cc53ba3..d6883151e7 100644 --- a/rpcs3/Emu/Cell/PPUThread.cpp +++ b/rpcs3/Emu/Cell/PPUThread.cpp @@ -1225,7 +1225,7 @@ extern void ppu_initialize() } // New PPU cache location - _main->cache = fs::get_config_dir() + "data/"; + _main->cache = fs::get_cache_dir() + "data/"; if (!Emu.GetTitleID().empty() && Emu.GetCat() != "1P") { diff --git a/rpcs3/Emu/RSX/Common/ProgramStateCache.cpp b/rpcs3/Emu/RSX/Common/ProgramStateCache.cpp index 2b441e9c34..01b83ad5b6 100644 --- a/rpcs3/Emu/RSX/Common/ProgramStateCache.cpp +++ b/rpcs3/Emu/RSX/Common/ProgramStateCache.cpp @@ -175,7 +175,7 @@ vertex_program_utils::vertex_program_metadata vertex_program_utils::analyse_vert if (g_cfg.video.log_programs) { - fs::file dump(fs::get_config_dir() + "shaderlog/vp_analyser.bin", fs::rewrite); + fs::file dump(fs::get_cache_dir() + "shaderlog/vp_analyser.bin", fs::rewrite); dump.write(&entry, 4); dump.write(data, 512 * 16); dump.close(); diff --git a/rpcs3/Emu/RSX/D3D12/D3D12PipelineState.h b/rpcs3/Emu/RSX/D3D12/D3D12PipelineState.h index 52c63cb238..f015c2011b 100644 --- a/rpcs3/Emu/RSX/D3D12/D3D12PipelineState.h +++ b/rpcs3/Emu/RSX/D3D12/D3D12PipelineState.h @@ -130,7 +130,7 @@ struct D3D12Traits } } - fs::file(fs::get_config_dir() + "shaderlog/FragmentProgram" + std::to_string(ID) + ".hlsl", fs::rewrite).write(shader); + fs::file(fs::get_cache_dir() + "shaderlog/FragmentProgram" + std::to_string(ID) + ".hlsl", fs::rewrite).write(shader); fragmentProgramData.id = (u32)ID; } @@ -141,7 +141,7 @@ struct D3D12Traits std::string shaderCode = VS.Decompile(); vertexProgramData.Compile(shaderCode, Shader::SHADER_TYPE::SHADER_TYPE_VERTEX); vertexProgramData.vertex_shader_input_count = RSXVP.rsx_vertex_inputs.size(); - fs::file(fs::get_config_dir() + "shaderlog/VertexProgram" + std::to_string(ID) + ".hlsl", fs::rewrite).write(shaderCode); + fs::file(fs::get_cache_dir() + "shaderlog/VertexProgram" + std::to_string(ID) + ".hlsl", fs::rewrite).write(shaderCode); vertexProgramData.id = (u32)ID; } diff --git a/rpcs3/Emu/RSX/GL/GLFragmentProgram.cpp b/rpcs3/Emu/RSX/GL/GLFragmentProgram.cpp index 93a7b1c65e..7b77b7108f 100644 --- a/rpcs3/Emu/RSX/GL/GLFragmentProgram.cpp +++ b/rpcs3/Emu/RSX/GL/GLFragmentProgram.cpp @@ -388,7 +388,7 @@ void GLFragmentProgram::Compile() const char* str = shader.c_str(); const int strlen = ::narrow(shader.length()); - fs::file(fs::get_config_dir() + "shaderlog/FragmentProgram" + std::to_string(id) + ".glsl", fs::rewrite).write(str); + fs::file(fs::get_cache_dir() + "shaderlog/FragmentProgram" + std::to_string(id) + ".glsl", fs::rewrite).write(str); glShaderSource(id, 1, &str, &strlen); glCompileShader(id); diff --git a/rpcs3/Emu/RSX/GL/GLHelpers.h b/rpcs3/Emu/RSX/GL/GLHelpers.h index 2ae764c770..6a1ee8012d 100644 --- a/rpcs3/Emu/RSX/GL/GLHelpers.h +++ b/rpcs3/Emu/RSX/GL/GLHelpers.h @@ -2398,7 +2398,7 @@ public: break; } - fs::file(fs::get_config_dir() + base_name + std::to_string(m_id) + ".glsl", fs::rewrite).write(str); + fs::file(fs::get_cache_dir() + base_name + std::to_string(m_id) + ".glsl", fs::rewrite).write(str); } glShaderSource(m_id, 1, &str, &length); diff --git a/rpcs3/Emu/RSX/GL/GLVertexProgram.cpp b/rpcs3/Emu/RSX/GL/GLVertexProgram.cpp index 59acd1d215..b31869b5ec 100644 --- a/rpcs3/Emu/RSX/GL/GLVertexProgram.cpp +++ b/rpcs3/Emu/RSX/GL/GLVertexProgram.cpp @@ -299,11 +299,11 @@ void GLVertexDecompilerThread::insertMainEnd(std::stringstream & OS) //RSX matrices passed already map to the [0, 1] range but mapping to classic OGL requires that we undo this step //This can be made unnecessary using the call glClipControl(GL_LOWER_LEFT, GL_ZERO_TO_ONE). //However, ClipControl only made it to opengl core in ver 4.5 though, so this is a workaround. - + //NOTE: It is completely valid for games to use very large w values, causing the post-multiplied z to be in the hundreds //It is therefore critical that this step is done post-transform and the result re-scaled by w //SEE Naruto: UNS - + //NOTE: On GPUs, poor fp32 precision means dividing z by w, then multiplying by w again gives slightly incorrect results //This equation is simplified algebraically to an addition and subreaction which gives more accurate results (Fixes flickering skybox in Dark Souls 2) //OS << " float ndc_z = gl_Position.z / gl_Position.w;\n"; @@ -345,7 +345,7 @@ void GLVertexProgram::Compile() const char* str = shader.c_str(); const int strlen = ::narrow(shader.length()); - fs::file(fs::get_config_dir() + "shaderlog/VertexProgram" + std::to_string(id) + ".glsl", fs::rewrite).write(str); + fs::file(fs::get_cache_dir() + "shaderlog/VertexProgram" + std::to_string(id) + ".glsl", fs::rewrite).write(str); glShaderSource(id, 1, &str, &strlen); glCompileShader(id); diff --git a/rpcs3/Emu/RSX/VK/VKFragmentProgram.cpp b/rpcs3/Emu/RSX/VK/VKFragmentProgram.cpp index 850e405063..a3ad70180a 100644 --- a/rpcs3/Emu/RSX/VK/VKFragmentProgram.cpp +++ b/rpcs3/Emu/RSX/VK/VKFragmentProgram.cpp @@ -403,7 +403,7 @@ void VKFragmentProgram::Decompile(const RSXFragmentProgram& prog) decompiler.Task(); shader.create(::glsl::program_domain::glsl_fragment_program, source); - + for (const ParamType& PT : decompiler.m_parr.params[PF_PARAM_UNIFORM]) { for (const ParamItem& PI : PT.items) @@ -422,7 +422,7 @@ void VKFragmentProgram::Decompile(const RSXFragmentProgram& prog) void VKFragmentProgram::Compile() { - fs::file(fs::get_config_dir() + "shaderlog/FragmentProgram" + std::to_string(id) + ".spirv", fs::rewrite).write(shader.get_source()); + fs::file(fs::get_cache_dir() + "shaderlog/FragmentProgram" + std::to_string(id) + ".spirv", fs::rewrite).write(shader.get_source()); handle = shader.compile(); } diff --git a/rpcs3/Emu/RSX/VK/VKVertexProgram.cpp b/rpcs3/Emu/RSX/VK/VKVertexProgram.cpp index 7d50146b4b..9ea9a678ca 100644 --- a/rpcs3/Emu/RSX/VK/VKVertexProgram.cpp +++ b/rpcs3/Emu/RSX/VK/VKVertexProgram.cpp @@ -353,7 +353,7 @@ void VKVertexProgram::Decompile(const RSXVertexProgram& prog) void VKVertexProgram::Compile() { - fs::file(fs::get_config_dir() + "shaderlog/VertexProgram" + std::to_string(id) + ".spirv", fs::rewrite).write(shader.get_source()); + fs::file(fs::get_cache_dir() + "shaderlog/VertexProgram" + std::to_string(id) + ".spirv", fs::rewrite).write(shader.get_source()); handle = shader.compile(); } diff --git a/rpcs3/Emu/System.cpp b/rpcs3/Emu/System.cpp index 9f585fbe47..917cc0e8dc 100644 --- a/rpcs3/Emu/System.cpp +++ b/rpcs3/Emu/System.cpp @@ -276,7 +276,7 @@ void Emulator::Init() { if (!g_tty) { - g_tty.open(fs::get_config_dir() + "TTY.log", fs::rewrite + fs::append); + g_tty.open(fs::get_cache_dir() + "TTY.log", fs::rewrite + fs::append); } idm::init(); @@ -318,7 +318,7 @@ void Emulator::Init() fs::create_dir(dev_hdd1 + "game/"); } - fs::create_path(fs::get_config_dir() + "shaderlog/"); + fs::create_path(fs::get_cache_dir() + "shaderlog/"); fs::create_path(fs::get_config_dir() + "captures/"); #ifdef WITH_GDB_DEBUGGER @@ -771,7 +771,7 @@ void Emulator::Load(bool add_only) // Initialize data/cache directory if (fs::is_dir(m_path)) { - m_cache_path = fs::get_config_dir() + "data/" + GetTitleID() + '/'; + m_cache_path = fs::get_cache_dir() + "data/" + GetTitleID() + '/'; LOG_NOTICE(LOADER, "Cache: %s", GetCachePath()); } else diff --git a/rpcs3/rpcs3qt/log_frame.cpp b/rpcs3/rpcs3qt/log_frame.cpp index c894d62d4d..5155fdbe12 100644 --- a/rpcs3/rpcs3qt/log_frame.cpp +++ b/rpcs3/rpcs3qt/log_frame.cpp @@ -155,7 +155,7 @@ log_frame::log_frame(std::shared_ptr guiSettings, QWidget *parent) setWidget(m_tabWidget); // Open or create TTY.log - m_tty_file.open(fs::get_config_dir() + "TTY.log", fs::read + fs::create); + m_tty_file.open(fs::get_cache_dir() + "TTY.log", fs::read + fs::create); CreateAndConnectActions(); diff --git a/rpcs3/rpcs3qt/rsx_debugger.cpp b/rpcs3/rpcs3qt/rsx_debugger.cpp index c519b0a087..be52339d2b 100644 --- a/rpcs3/rpcs3qt/rsx_debugger.cpp +++ b/rpcs3/rpcs3qt/rsx_debugger.cpp @@ -671,7 +671,7 @@ void rsx_debugger::GetMemory() dump += '\n'; } - fs::file(fs::get_config_dir() + "command_dump.log", fs::rewrite).write(dump); + fs::file(fs::get_cache_dir() + "command_dump.log", fs::rewrite).write(dump); for (u32 i = 0;i < frame_debug.draw_calls.size(); i++) m_list_captured_draw_calls->setItem(i, 0, new QTableWidgetItem(qstr(frame_debug.draw_calls[i].name)));