#include "stdafx.h" #include "disc.h" #include "PSF.h" #include "util/logs.hpp" #include "util/StrUtil.h" #include "Emu/System.h" #include "Emu/system_utils.hpp" LOG_CHANNEL(disc_log, "DISC"); namespace disc { disc_type get_disc_type(const std::string& path, std::string& disc_root, std::string& ps3_game_dir) { disc_type type = disc_type::unknown; disc_root.clear(); ps3_game_dir.clear(); if (path.empty()) { disc_log.error("Can not determine disc type. Path is empty."); return disc_type::invalid; } if (!fs::is_dir(path)) { disc_log.error("Can not determine disc type. Path not a directory: '%s'", path); return disc_type::invalid; } // Check for PS3 game first. std::string elf_path; if (const game_boot_result result = Emulator::GetElfPathFromDir(elf_path, path); result == game_boot_result::no_errors) { // Every error past this point is considered a corrupt disc. std::string sfb_dir; const std::string elf_dir = fs::get_parent_dir(elf_path); Emulator::GetBdvdDir(disc_root, sfb_dir, ps3_game_dir, elf_dir); if (!fs::is_dir(disc_root) || !fs::is_dir(sfb_dir) || ps3_game_dir.empty()) { disc_log.error("Not a PS3 disc: invalid folder (bdvd_dir='%s', sfb_dir='%s', game_dir='%s')", disc_root, sfb_dir, ps3_game_dir); return disc_type::invalid; } // Load PARAM.SFO const std::string sfo_dir = rpcs3::utils::get_sfo_dir_from_game_path(elf_dir + "/../", ""); const psf::registry _psf = psf::load_object(sfo_dir + "/PARAM.SFO"); if (_psf.empty()) { disc_log.error("Not a PS3 disc: Corrupted PARAM.SFO found! (path='%s/PARAM.SFO')", sfo_dir); return disc_type::invalid; } const std::string cat = std::string(psf::get_string(_psf, "CATEGORY")); if (cat != "DG") { disc_log.error("Not a PS3 disc: Wrong category '%s'.", cat); return disc_type::invalid; } return disc_type::ps3; } disc_log.notice("Not a PS3 disc: Elf not found. Looking for SYSTEM.CNF... (path='%s')", path); std::vector lines; // Try to find SYSTEM.CNF for (std::string search_dir = path;;) { if (fs::file file(search_dir + "/SYSTEM.CNF"); file) { disc_root = search_dir + "/"; lines = fmt::split(file.to_string(), {"\n"}); break; } std::string parent_dir = fs::get_parent_dir(search_dir); if (parent_dir.size() == search_dir.size()) { // Keep looking until root directory is reached disc_log.error("SYSTEM.CNF not found in path: '%s'", path); return disc_type::invalid; } search_dir = std::move(parent_dir); } for (usz i = 0; i < lines.size(); i++) { const std::string& line = lines[i]; const usz pos = line.find('='); if (pos == umax) { continue; } const std::string key = fmt::trim(line.substr(0, pos)); std::string value; if (pos != (line.size() - 1)) { value = fmt::trim(line.substr(pos + 1)); } if (value.empty() && i != (lines.size() - 1) && line.size() != 1) { // Some games have a character on the last line of the file, don't print the error in those cases. disc_log.warning("Unusual or malformed entry in SYSTEM.CNF ignored: %s", line); continue; } if (key == "BOOT2") { disc_log.notice("SYSTEM.CNF - Detected PS2 Disc = %s", value); type = disc_type::ps2; } else if (key == "BOOT") { disc_log.notice("SYSTEM.CNF - Detected PSX/PSone Disc = %s", value); type = disc_type::ps1; } else if (key == "VMODE") { disc_log.notice("SYSTEM.CNF - Disc region type = %s", value); } else if (key == "VER") { disc_log.notice("SYSTEM.CNF - Software version = %s", value); } } if (type == disc_type::unknown) { disc_log.error("SYSTEM.CNF - Disc is not a PSX/PSone or PS2 game!"); } return type; } } // namespace disc