@@ -84,17 +84,13 @@ std::vector<std::string> SatisfactorySave::IoStoreFile::getAllAssetFilenames() c
8484}
8585
8686std::vector<char > SatisfactorySave::IoStoreFile::readAssetFileContent (const std::string& filename) {
87- if (dirIndex_ == nullptr ) {
88- throw std::runtime_error (" Missing directory index!" );
89- }
90- if (!dirIndex_->directoryEntries ().contains (filename)) {
91- throw std::runtime_error (" Asset file not found in utoc: " + filename);
92- }
93-
94- // UserData of directory index file entry is index to chunk data
95- uint32_t chunkIdx = dirIndex_->directoryEntries ().at (filename);
87+ return readChunkContent (getChunkIdx (filename));
88+ }
9689
97- return readChunkContent (chunkIdx);
90+ std::unique_ptr<SatisfactorySave::IStream> SatisfactorySave::IoStoreFile::getAssetFileStream (
91+ const std::string& filename) {
92+ return std::make_unique<AssetFileIStream>(std::static_pointer_cast<IoStoreFile>(shared_from_this ()),
93+ getChunkIdx (filename));
9894}
9995
10096std::vector<char > SatisfactorySave::IoStoreFile::readChunkContent (std::size_t chunkIdx) {
@@ -111,30 +107,46 @@ std::vector<char> SatisfactorySave::IoStoreFile::readChunkContent(std::size_t ch
111107 // Allocate output
112108 std::vector<char > buf (chunk.GetLength ());
113109
114- auto & ar = *ucasAr_;
115-
116110 // Loop over compression blocks
117111 for (uint32_t i = 0 ; i < compBlockNum; i++) {
118- const auto & compBlock = utoc_.CompressionBlocks [compBlockIdx + i];
119-
120- // Validate that uncompressed size of all compression blocks (except the last one) is block size.
121- if (i < compBlockNum - 1 && compBlock.GetUncompressedSize () != blockSize) {
122- throw std::runtime_error (" Unexpected uncompressed block size" );
123- }
124-
125- ar.seek (compBlock.GetOffset ());
126- const auto compMethod = utoc_.CompressionMethods .at (compBlock.GetCompressionMethodIndex ());
127- if (compMethod == " None" ) {
128- // Uncompressed, copy directly to out buffer.
129- ar.serializeRaw (buf.data () + i * blockSize, compBlock.GetCompressedSize ());
130- } else if (compMethod == " Oodle" ) {
131- const auto comp_buf = ar.read_buffer (compBlock.GetCompressedSize ());
132- oodleDecompress (buf.data () + i * blockSize, compBlock.GetUncompressedSize (), comp_buf.data (),
133- compBlock.GetCompressedSize ());
134- } else {
135- throw std::runtime_error (" Unknown compression method: " + compMethod);
136- }
112+ const uint32_t expectedSize =
113+ (i < compBlockNum - 1 ) ? blockSize : chunk.GetLength () - (compBlockNum - 1 ) * blockSize;
114+ readCompressionBlock (compBlockIdx + i, buf.data () + i * blockSize, expectedSize);
137115 }
138116
139117 return buf;
140118}
119+
120+ uint32_t SatisfactorySave::IoStoreFile::getChunkIdx (const std::string& filename) const {
121+ if (dirIndex_ == nullptr ) {
122+ throw std::runtime_error (" Missing directory index!" );
123+ }
124+ if (!dirIndex_->directoryEntries ().contains (filename)) {
125+ throw std::runtime_error (" Asset file not found in utoc: " + filename);
126+ }
127+
128+ // UserData of directory index file entry is index to chunk data
129+ return dirIndex_->directoryEntries ().at (filename);
130+ }
131+
132+ void SatisfactorySave::IoStoreFile::readCompressionBlock (uint64_t blockIdx, char * dst, uint32_t expectedSize) {
133+ auto & ar = *ucasAr_;
134+ const auto & compBlock = utoc_.CompressionBlocks [blockIdx];
135+
136+ // Validate that uncompressed size of all compression blocks (except the last one) is block size.
137+ if (compBlock.GetUncompressedSize () != expectedSize) {
138+ throw std::runtime_error (" Unexpected uncompressed block size" );
139+ }
140+
141+ ar.seek (compBlock.GetOffset ());
142+ const auto compMethod = utoc_.CompressionMethods .at (compBlock.GetCompressionMethodIndex ());
143+ if (compMethod == " None" ) {
144+ // Uncompressed, copy directly to out buffer.
145+ ar.serializeRaw (dst, compBlock.GetCompressedSize ());
146+ } else if (compMethod == " Oodle" ) {
147+ const auto comp_buf = ar.read_buffer (compBlock.GetCompressedSize ());
148+ oodleDecompress (dst, compBlock.GetUncompressedSize (), comp_buf.data (), compBlock.GetCompressedSize ());
149+ } else {
150+ throw std::runtime_error (" Unknown compression method: " + compMethod);
151+ }
152+ }
0 commit comments