- Fixed a bug where folders where not created in the correct location which led to missing folders and files (incomplete/wrong extraction)
This commit is contained in:
parent
7e54255d29
commit
12a8cf5ee9
|
@ -41,17 +41,6 @@ u32 GetPFSCOffset(std::span<const u8> pfs_image) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::filesystem::path findDirectory(const std::filesystem::path& rootFolder,
|
|
||||||
const std::filesystem::path& targetDirectory) {
|
|
||||||
for (const auto& entry : std::filesystem::recursive_directory_iterator(rootFolder)) {
|
|
||||||
if (std::filesystem::is_directory(entry) &&
|
|
||||||
entry.path().filename() == targetDirectory.filename()) {
|
|
||||||
return entry.path();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return std::filesystem::path(); // Return an empty path if not found
|
|
||||||
}
|
|
||||||
|
|
||||||
PKG::PKG() = default;
|
PKG::PKG() = default;
|
||||||
|
|
||||||
PKG::~PKG() = default;
|
PKG::~PKG() = default;
|
||||||
|
@ -198,11 +187,13 @@ bool PKG::Extract(const std::string& filepath, const std::filesystem::path& extr
|
||||||
|
|
||||||
u32 ent_size = 0;
|
u32 ent_size = 0;
|
||||||
u32 ndinode = 0;
|
u32 ndinode = 0;
|
||||||
|
int ndinode_counter = 0;
|
||||||
|
bool dinode_reached = false;
|
||||||
std::vector<char> compressedData;
|
std::vector<char> compressedData;
|
||||||
std::vector<char> decompressedData(0x10000);
|
std::vector<char> decompressedData(0x10000);
|
||||||
bool dinode_reached = false;
|
extractPaths[2] = extract_path.parent_path() / GetTitleID();
|
||||||
// Get iNdoes.
|
|
||||||
|
// Get iNdoes and Dirents.
|
||||||
for (int i = 0; i < num_blocks; i++) {
|
for (int i = 0; i < num_blocks; i++) {
|
||||||
const u64 sectorOffset = sectorMap[i];
|
const u64 sectorOffset = sectorMap[i];
|
||||||
const u64 sectorSize = sectorMap[i + 1] - sectorOffset;
|
const u64 sectorSize = sectorMap[i + 1] - sectorOffset;
|
||||||
|
@ -253,59 +244,32 @@ bool PKG::Extract(const std::string& filepath, const std::filesystem::path& extr
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dot != '.' && dotdot != "..") {
|
|
||||||
end_reached = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
ent_size = dirent.entsize;
|
ent_size = dirent.entsize;
|
||||||
auto& table = fsTable.emplace_back();
|
auto& table = fsTable.emplace_back();
|
||||||
table.name = std::string(dirent.name, dirent.namelen);
|
table.name = std::string(dirent.name, dirent.namelen);
|
||||||
table.inode = dirent.ino;
|
table.inode = dirent.ino;
|
||||||
table.type = dirent.type;
|
table.type = dirent.type;
|
||||||
|
|
||||||
if (table.type == PFS_DIR) {
|
if (table.type == PFS_CURRENT_DIR) {
|
||||||
folderMap[table.inode] = table.name;
|
current_dir = extractPaths[table.inode];
|
||||||
|
}
|
||||||
|
extractPaths[table.inode] =
|
||||||
|
current_dir.string() / std::filesystem::path(table.name);
|
||||||
|
|
||||||
|
if (table.type == PFS_FILE || table.type == PFS_DIR) {
|
||||||
|
if (table.type == PFS_DIR) { // Create dirs.
|
||||||
|
std::filesystem::create_directory(extractPaths[table.inode]);
|
||||||
|
}
|
||||||
|
ndinode_counter++;
|
||||||
|
if ((ndinode_counter + 3) == ndinode) // 3 for root, uroot and flat_path_table.
|
||||||
|
end_reached = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (end_reached) {
|
||||||
// Seems to be the last entry, at least for the games I tested. To check as we go.
|
|
||||||
const std::string_view rightsprx(&decompressedData[0x40], 10);
|
|
||||||
if (rightsprx == "right.sprx" || end_reached) {
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create Folders.
|
|
||||||
folderMap[2] = GetTitleID(); // Set up game path instead of calling it uroot
|
|
||||||
game_dir = extract_path.parent_path();
|
|
||||||
title_dir = game_dir / GetTitleID();
|
|
||||||
|
|
||||||
for (int i = 0; i < fsTable.size(); i++) {
|
|
||||||
const u32 inode_number = fsTable[i].inode;
|
|
||||||
const u32 inode_type = fsTable[i].type;
|
|
||||||
const auto inode_name = fsTable[i].name;
|
|
||||||
|
|
||||||
if (inode_type == PFS_CURRENT_DIR) {
|
|
||||||
current_dir = folderMap[inode_number];
|
|
||||||
} else if (inode_type == PFS_PARENT_DIR) {
|
|
||||||
parent_dir = folderMap[inode_number];
|
|
||||||
// Skip uroot folder. we create our own game uid folder
|
|
||||||
if (i > 1) {
|
|
||||||
const auto par_dir = inode_number == 2 ? findDirectory(game_dir, parent_dir)
|
|
||||||
: findDirectory(title_dir, parent_dir);
|
|
||||||
const auto cur_dir = findDirectory(par_dir, current_dir);
|
|
||||||
|
|
||||||
if (cur_dir == "") {
|
|
||||||
extract_path = par_dir / current_dir;
|
|
||||||
std::filesystem::create_directories(extract_path);
|
|
||||||
} else {
|
|
||||||
extract_path = cur_dir;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
extractMap[inode_number] = extract_path.string();
|
|
||||||
}
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -318,10 +282,9 @@ void PKG::ExtractFiles(const int& index) {
|
||||||
int sector_loc = iNodeBuf[inode_number].loc;
|
int sector_loc = iNodeBuf[inode_number].loc;
|
||||||
int nblocks = iNodeBuf[inode_number].Blocks;
|
int nblocks = iNodeBuf[inode_number].Blocks;
|
||||||
int bsize = iNodeBuf[inode_number].Size;
|
int bsize = iNodeBuf[inode_number].Size;
|
||||||
std::string file_extracted = extractMap[inode_number] + "/" + inode_name;
|
|
||||||
|
|
||||||
Common::FS::IOFile inflated;
|
Common::FS::IOFile inflated;
|
||||||
inflated.Open(file_extracted, Common::FS::FileAccessMode::Write);
|
inflated.Open(extractPaths[inode_number].string(), Common::FS::FileAccessMode::Write);
|
||||||
|
|
||||||
Common::FS::IOFile pkgFile; // Open the file for each iteration to avoid conflict.
|
Common::FS::IOFile pkgFile; // Open the file for each iteration to avoid conflict.
|
||||||
pkgFile.Open(pkgpath, Common::FS::FileAccessMode::Read);
|
pkgFile.Open(pkgpath, Common::FS::FileAccessMode::Read);
|
||||||
|
|
|
@ -114,8 +114,7 @@ private:
|
||||||
char pkgTitleID[9];
|
char pkgTitleID[9];
|
||||||
PKGHeader pkgheader;
|
PKGHeader pkgheader;
|
||||||
|
|
||||||
std::unordered_map<int, std::string> folderMap;
|
std::unordered_map<int, std::filesystem::path> extractPaths;
|
||||||
std::unordered_map<int, std::string> extractMap;
|
|
||||||
std::vector<pfs_fs_table> fsTable;
|
std::vector<pfs_fs_table> fsTable;
|
||||||
std::vector<Inode> iNodeBuf;
|
std::vector<Inode> iNodeBuf;
|
||||||
std::vector<u64> sectorMap;
|
std::vector<u64> sectorMap;
|
||||||
|
@ -130,8 +129,5 @@ private:
|
||||||
|
|
||||||
std::filesystem::path pkgpath;
|
std::filesystem::path pkgpath;
|
||||||
std::filesystem::path current_dir;
|
std::filesystem::path current_dir;
|
||||||
std::filesystem::path parent_dir;
|
|
||||||
std::filesystem::path extract_path;
|
std::filesystem::path extract_path;
|
||||||
std::filesystem::path game_dir;
|
|
||||||
std::filesystem::path title_dir;
|
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in New Issue