mirror of
https://github.com/RPCSX/rpcsx.git
synced 2026-04-05 14:37:08 +00:00
Add RPCS3/games/ for automatic games detection, support PSN games outside HDD0 (#12982)
* SFO: Do not load PARAM.SFO with illegal TITLE_ID * Add support for PSN games outside HDD0 * Add RPCS3/games/ for automatic game detection
This commit is contained in:
parent
8d9dd1d19c
commit
ad3ea966cb
7 changed files with 135 additions and 22 deletions
|
|
@ -374,7 +374,10 @@ void Emulator::Init(bool add_only)
|
|||
if (!fs::create_path(path))
|
||||
{
|
||||
sys_log.fatal("Failed to create path: %s (%s)", path, fs::g_tls_error);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
const std::string save_path = dev_hdd0 + "home/" + m_usr + "/savedata/";
|
||||
|
|
@ -419,6 +422,11 @@ void Emulator::Init(bool add_only)
|
|||
make_path_verbose(fs::get_config_dir() + "sounds/");
|
||||
make_path_verbose(patch_engine::get_patches_path());
|
||||
|
||||
if (const std::string games_common = fs::get_config_dir() + "/games"; make_path_verbose(games_common))
|
||||
{
|
||||
fs::write_file(user_path + "/Disc Games Can Be Put Here For Automatic Detection.txt", fs::create + fs::excl + fs::write, ""s);
|
||||
}
|
||||
|
||||
if (add_only)
|
||||
{
|
||||
// We don't need to initialize the rest if we only add games
|
||||
|
|
@ -961,6 +969,21 @@ game_boot_result Emulator::Load(const std::string& title_id, bool add_only, bool
|
|||
{
|
||||
m_path = rpcs3::utils::get_hdd0_dir();
|
||||
m_path += std::string_view(argv[0]).substr(9);
|
||||
|
||||
constexpr auto game0_path = "/dev_hdd0/game/"sv;
|
||||
|
||||
if (argv[0].starts_with(game0_path) && !fs::is_file(vfs::get(argv[0])))
|
||||
{
|
||||
std::string title_id = argv[0].substr(game0_path.size());
|
||||
title_id = title_id.substr(0, title_id.find_last_not_of('/'));
|
||||
|
||||
// Try to load game directory from list if available
|
||||
if (auto node = (title_id.empty() ? YAML::Node{} : games[title_id]))
|
||||
{
|
||||
disc = node.Scalar();
|
||||
m_path = disc + argv[0].substr(game0_path.size() + title_id.size());
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (argv[0].starts_with("/dev_flash"sv))
|
||||
{
|
||||
|
|
@ -1332,7 +1355,6 @@ game_boot_result Emulator::Load(const std::string& title_id, bool add_only, bool
|
|||
|
||||
// Detect boot location
|
||||
const std::string hdd0_game = vfs::get("/dev_hdd0/game/");
|
||||
const std::string hdd0_disc = vfs::get("/dev_hdd0/disc/");
|
||||
const bool from_hdd0_game = IsPathInsideDir(m_path, hdd0_game);
|
||||
const bool from_dev_flash = IsPathInsideDir(m_path, g_cfg_vfs.get_dev_flash());
|
||||
|
||||
|
|
@ -1358,6 +1380,7 @@ game_boot_result Emulator::Load(const std::string& title_id, bool add_only, bool
|
|||
// Booting disc game from wrong location
|
||||
sys_log.error("Disc game %s found at invalid location /dev_hdd0/game/", m_title_id);
|
||||
|
||||
const std::string hdd0_disc = vfs::get("/dev_hdd0/disc/");
|
||||
const std::string dst_dir = hdd0_disc + sfb_dir.substr(hdd0_game.size());
|
||||
|
||||
// Move and retry from correct location
|
||||
|
|
@ -1483,6 +1506,23 @@ game_boot_result Emulator::Load(const std::string& title_id, bool add_only, bool
|
|||
else if (m_cat != "DG" && m_cat != "GD")
|
||||
{
|
||||
// Don't need /dev_bdvd
|
||||
|
||||
if (!m_title_id.empty() && !from_hdd0_game && m_cat == "HG")
|
||||
{
|
||||
// Add HG games not in HDD0 to games.yml
|
||||
games[m_title_id] = m_sfo_dir;
|
||||
YAML::Emitter out;
|
||||
out << games;
|
||||
|
||||
fs::pending_file temp(fs::get_config_dir() + "/games.yml");
|
||||
|
||||
if (!temp.file || temp.file.write(out.c_str(), out.size()), !temp.commit())
|
||||
{
|
||||
sys_log.error("Failed to save HG game location of title '%s' (%s)", m_title_id, fs::g_tls_error);
|
||||
}
|
||||
|
||||
vfs::mount("/dev_hdd0/game/" + m_title_id, m_sfo_dir + '/');
|
||||
}
|
||||
}
|
||||
else if (m_cat == "DG" && from_hdd0_game && disc.empty())
|
||||
{
|
||||
|
|
@ -1812,6 +1852,12 @@ game_boot_result Emulator::Load(const std::string& title_id, bool add_only, bool
|
|||
argv[0] = "/dev_flash" + resolved_path.substr(GetCallbacks().resolve_path(g_cfg_vfs.get_dev_flash()).size());
|
||||
m_dir = fs::get_parent_dir(argv[0]) + '/';
|
||||
}
|
||||
else if (!m_title_id.empty() && m_cat == "HG")
|
||||
{
|
||||
m_dir = "/dev_hdd0/game/" + m_title_id + '/';
|
||||
argv[0] = m_dir + unescape(resolved_path.substr(GetCallbacks().resolve_path(m_sfo_dir).size()));
|
||||
sys_log.notice("Boot path: %s", m_dir);
|
||||
}
|
||||
else if (g_cfg.vfs.host_root)
|
||||
{
|
||||
// For homebrew
|
||||
|
|
@ -2899,6 +2945,61 @@ std::set<std::string> Emulator::GetGameDirs() const
|
|||
return dirs;
|
||||
}
|
||||
|
||||
void Emulator::AddGamesFromDir(const std::string& path)
|
||||
{
|
||||
if (!IsStopped())
|
||||
return;
|
||||
|
||||
const std::string games_yml = fs::get_cache_dir() + "/games.yml";
|
||||
|
||||
std::string content_before, content_after;
|
||||
|
||||
if (fs::file fd{games_yml})
|
||||
{
|
||||
content_before = fd.to_string();
|
||||
}
|
||||
|
||||
// search dropped path first or else the direct parent to an elf is wrongly skipped
|
||||
if (const auto error = BootGame(path, "", false, true); error == game_boot_result::no_errors)
|
||||
{
|
||||
if (fs::file fd{games_yml, fs::read + fs::isfile})
|
||||
{
|
||||
content_after = fd.to_string();
|
||||
}
|
||||
|
||||
if (content_before != content_after)
|
||||
{
|
||||
sys_log.notice("Registered game directory: %s", path);
|
||||
content_before = content_after;
|
||||
}
|
||||
}
|
||||
|
||||
// search direct subdirectories, that way we can drop one folder containing all games
|
||||
for (auto&& dir_entry : fs::dir(path))
|
||||
{
|
||||
if (!dir_entry.is_directory || dir_entry.name == "." || dir_entry.name == "..")
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
const std::string dir_path = path + '/' + dir_entry.name;
|
||||
|
||||
if (const auto error = BootGame(dir_path, "", false, true); error == game_boot_result::no_errors)
|
||||
{
|
||||
if (fs::file fd{games_yml, fs::read + fs::isfile})
|
||||
{
|
||||
content_after = fd.to_string();
|
||||
}
|
||||
|
||||
if (content_before != content_after)
|
||||
{
|
||||
sys_log.notice("Registered game directory: %s", dir_path);
|
||||
content_before = content_after;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool Emulator::IsPathInsideDir(std::string_view path, std::string_view dir) const
|
||||
{
|
||||
const std::string dir_path = GetCallbacks().resolve_path(dir);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue