| 787 | } |
| 788 | |
| 789 | static std::optional<GameInfo> |
| 790 | fetchGameInfo(const psf::registry &psf, |
| 791 | std::filesystem::path psfRootPath = {}) { |
| 792 | auto titleId = std::string(psf::get_string(psf, "TITLE_ID")); |
| 793 | auto name = std::string(psf::get_string(psf, "TITLE")); |
| 794 | auto bootable = psf::get_integer(psf, "BOOTABLE", 0); |
| 795 | auto category = psf::get_string(psf, "CATEGORY"); |
| 796 | |
| 797 | if (!bootable || titleId.empty()) { |
| 798 | return {}; |
| 799 | } |
| 800 | |
| 801 | bool isDiscGame = category == "DG"; |
| 802 | |
| 803 | std::string path; |
| 804 | |
| 805 | if (!isDiscGame) { |
| 806 | path = rpcs3::utils::get_hdd0_dir() + "game/" + titleId + "/"; |
| 807 | } else { |
| 808 | if (psfRootPath.empty()) { |
| 809 | path = fs::get_config_dir() + "games/" + titleId + "/"; |
| 810 | } else { |
| 811 | // Locate game root path |
| 812 | if (psfRootPath.filename() == "USRDIR") { |
| 813 | psfRootPath = psfRootPath.parent_path(); |
| 814 | } |
| 815 | |
| 816 | if (psfRootPath.filename() == "PS3_GAME") { |
| 817 | psfRootPath = psfRootPath.parent_path(); |
| 818 | } |
| 819 | |
| 820 | path = psfRootPath; |
| 821 | if (!path.ends_with('/')) { |
| 822 | path += '/'; |
| 823 | } |
| 824 | } |
| 825 | } |
| 826 | |
| 827 | auto dataPath = isDiscGame ? path + "PS3_GAME/" : path; |
| 828 | auto iconPath = dataPath + "ICON0.PNG"; |
| 829 | auto moviePath = dataPath + "ICON1.PAM"; |
| 830 | |
| 831 | int flags = 0; |
| 832 | |
| 833 | if (!isDiscGame) { |
| 834 | auto ebootPath = locateEbootPath(path); |
| 835 | |
| 836 | bool isLocked = false; |
| 837 | |
| 838 | if (!ebootPath.empty()) { |
| 839 | if (fs::file eboot{ebootPath}; |
| 840 | eboot && eboot.size() >= 4 && eboot.read<u32>() == "SCE\0"_u32) { |
| 841 | isLocked = !decrypt_self(eboot); |
| 842 | } |
| 843 | } |
| 844 | |
| 845 | if (isLocked) { |
| 846 | flags |= kGameFlagLocked; |
no test coverage detected