|
1 | 1 | #include "Pak/IoStoreFile.h" |
2 | 2 |
|
| 3 | +#include <cstring> |
| 4 | + |
3 | 5 | #include "GameTypes/UE/Core/IO/IoStore.h" |
| 6 | +#include "IO/MemoryStreams.h" |
| 7 | + |
| 8 | +SatisfactorySave::DirectoryIndexReader::DirectoryIndexReader(const FIoDirectoryIndexResource& res) : res_(res) { |
| 9 | + if (!res_.MountPoint.starts_with("../../../")) { |
| 10 | + throw std::runtime_error("Invalid mount point"); |
| 11 | + } |
| 12 | + parseDir(0, res_.MountPoint.substr(9)); |
| 13 | +} |
| 14 | + |
| 15 | +void SatisfactorySave::DirectoryIndexReader::parseDir(uint32_t dir_idx, const std::string& path) { |
| 16 | + if (dir_idx == none) { |
| 17 | + return; |
| 18 | + } |
| 19 | + const auto& entry = res_.DirectoryEntries[dir_idx]; |
| 20 | + const std::string name = (entry.Name != none) ? (res_.StringTable[entry.Name] + "/") : ""; |
| 21 | + // children |
| 22 | + parseDir(entry.FirstChildEntry, path + name); |
| 23 | + // siblings |
| 24 | + parseDir(entry.NextSiblingEntry, path); |
| 25 | + // files |
| 26 | + parseFile(entry.FirstFileEntry, path + name); |
| 27 | +} |
| 28 | + |
| 29 | +void SatisfactorySave::DirectoryIndexReader::parseFile(uint32_t file_idx, const std::string& path) { |
| 30 | + if (file_idx == none) { |
| 31 | + return; |
| 32 | + } |
| 33 | + const auto& entry = res_.FileEntries[file_idx]; |
| 34 | + const std::string filename = path + res_.StringTable[entry.Name]; |
| 35 | + if (directoryEntries_.contains(filename)) { |
| 36 | + throw std::runtime_error("Directory filename entry is not unique!"); |
| 37 | + } |
| 38 | + directoryEntries_[filename] = entry.UserData; |
| 39 | + |
| 40 | + parseFile(entry.NextFileEntry, path); |
| 41 | +} |
4 | 42 |
|
5 | 43 | SatisfactorySave::IoStoreFile::IoStoreFile(const std::filesystem::path& path) { |
6 | 44 | if (!std::filesystem::is_regular_file(path)) { |
7 | 45 | throw std::runtime_error("IoStore file invalid: " + path.string()); |
8 | 46 | } |
9 | 47 |
|
10 | | - ioStoreAr_ = std::make_unique<IFStreamArchive>(path); |
11 | | - auto& ar = *ioStoreAr_; |
12 | | - |
13 | | - FIoStoreTocResource utoc; |
14 | | - ar << utoc; |
| 48 | + IFStreamArchive utocAr(path); |
| 49 | + utocAr << utoc_; |
15 | 50 |
|
16 | 51 | // Debug validation |
17 | | - if (ar.tell() != ar.size()) { |
| 52 | + if (utocAr.tell() != utocAr.size()) { |
18 | 53 | throw std::runtime_error("utoc file not fully read!"); |
19 | 54 | } |
| 55 | + |
| 56 | + if (!utoc_.DirectoryIndexBuffer.empty()) { |
| 57 | + auto buf = std::make_unique<std::vector<char>>(); |
| 58 | + buf->resize(utoc_.DirectoryIndexBuffer.size()); |
| 59 | + std::memcpy(buf->data(), utoc_.DirectoryIndexBuffer.data(), utoc_.DirectoryIndexBuffer.size()); |
| 60 | + IStreamArchive dirIndexAr(std::make_unique<MemIStream>(std::move(buf))); |
| 61 | + |
| 62 | + FIoDirectoryIndexResource dirIndexRes; |
| 63 | + dirIndexAr << dirIndexRes; |
| 64 | + |
| 65 | + dirIndex_ = std::make_unique<DirectoryIndexReader>(dirIndexRes); |
| 66 | + } |
| 67 | +} |
| 68 | + |
| 69 | +std::vector<std::string> SatisfactorySave::IoStoreFile::getAllAssetFilenames() const { |
| 70 | + if (dirIndex_ == nullptr) { |
| 71 | + return {}; |
| 72 | + } |
| 73 | + |
| 74 | + std::vector<std::string> filenames; |
| 75 | + filenames.reserve(dirIndex_->directoryEntries().size()); |
| 76 | + for (const auto& entry : dirIndex_->directoryEntries()) { |
| 77 | + filenames.emplace_back(entry.first); |
| 78 | + } |
| 79 | + return filenames; |
| 80 | +} |
| 81 | + |
| 82 | +std::vector<char> SatisfactorySave::IoStoreFile::readAssetFileContent(const std::string& filename) { |
| 83 | + // TODO |
| 84 | + return {}; |
20 | 85 | } |
0 commit comments