use of info.ata4.junity.bundle.BundleEntry in project disunity by ata4.
the class BundleReader method read.
public Bundle read() throws BundleException, IOException {
bundle = new Bundle();
in.position(0);
BundleHeader header = bundle.header();
in.readStruct(header);
// check signature
if (!header.hasValidSignature()) {
throw new BundleException("Invalid signature");
}
List<BundleEntryInfo> entryInfos = bundle.entryInfos();
if (header.compressedDataHeaderSize() > 0) {
if (header.dataHeaderAtEndOfFile()) {
in.position(header.completeFileSize() - header.compressedDataHeaderSize());
}
// build an input stream for the uncompressed data header
InputStream headerIn = new BoundedInputStream(in.stream(), header.compressedDataHeaderSize());
DataReader inData;
switch(header.dataHeaderCompressionScheme()) {
default:
case 0:
// Not compressed
inData = DataReaders.forInputStream(headerIn);
case 1:
// LZMA
inData = DataReaders.forInputStream(new CountingInputStream(new LzmaInputStream(headerIn)));
case 3:
// LZ4
byte[] compressed = new byte[header.compressedDataHeaderSize()];
byte[] decompressed = new byte[(int) header.dataHeaderSize()];
headerIn.read(compressed);
LZ4JavaSafeFastDecompressor.INSTANCE.decompress(compressed, decompressed);
inData = DataReaders.forByteBuffer(ByteBuffer.wrap(decompressed));
}
// Block info: not captured for now
{
// 16 bytes unknown
byte[] unknown = new byte[16];
inData.readBytes(unknown);
int storageBlocks = inData.readInt();
for (int i = 0; i < storageBlocks; ++i) {
inData.readUnsignedInt();
inData.readUnsignedInt();
inData.readUnsignedShort();
}
}
int files = inData.readInt();
for (int i = 0; i < files; i++) {
BundleEntryInfo entryInfo = new BundleEntryInfoFS();
inData.readStruct(entryInfo);
entryInfos.add(entryInfo);
}
} else {
// raw or web header
long dataHeaderSize = header.dataHeaderSize();
if (dataHeaderSize == 0) {
// old stream versions don't store the data header size, so use a large
// fixed number instead
dataHeaderSize = 4096;
}
InputStream is = dataInputStream(0, dataHeaderSize);
DataReader inData = DataReaders.forInputStream(is);
int files = inData.readInt();
for (int i = 0; i < files; i++) {
BundleEntryInfo entryInfo = new BundleEntryInfo();
inData.readStruct(entryInfo);
entryInfos.add(entryInfo);
}
}
// sort entries by offset so that they're in the order in which they
// appear in the file, which is convenient for compressed bundles
entryInfos.sort((a, b) -> Long.compare(a.offset(), b.offset()));
List<BundleEntry> entries = bundle.entries();
entryInfos.forEach(entryInfo -> {
entries.add(new BundleInternalEntry(entryInfo, this::inputStreamForEntry));
});
return bundle;
}
use of info.ata4.junity.bundle.BundleEntry in project disunity by ata4.
the class BundleUtils method byteChannelForEntry.
public static SeekableByteChannel byteChannelForEntry(BundleEntry entry) throws IOException {
SeekableByteChannel chan;
// check if the entry is larger than 128 MiB
long size = entry.size();
if (size > 1 << 27) {
// copy entry to temporary file
Path tmpFile = Files.createTempFile("disunity", null);
Files.copy(entry.inputStream(), tmpFile, REPLACE_EXISTING);
chan = Files.newByteChannel(tmpFile, READ, DELETE_ON_CLOSE);
} else {
// copy entry to memory
ByteBuffer bb = ByteBuffer.allocateDirect((int) size);
IOUtils.copy(entry.inputStream(), new ByteBufferOutputStream(bb));
bb.flip();
chan = new ByteBufferChannel(bb);
}
return chan;
}
use of info.ata4.junity.bundle.BundleEntry in project disunity by ata4.
the class AssetCommand method runFileRecursive.
@Override
protected void runFileRecursive(Path file) {
if (BundleUtils.isBundle(file)) {
// file is a bundle, load serialized files from it
try (BundleReader bundleReader = new BundleReader(file)) {
Bundle bundle = bundleReader.read();
bundle.entries().stream().filter(not(BundleEntry::isLibrary)).filter(not(BundleEntry::isResource)).forEach(uncheck(entry -> {
try (SerializedFileReader reader = new SerializedFileReader(BundleUtils.dataReaderForEntry(entry))) {
SerializedFile serialized = reader.read();
runSerializedFile(file.resolve(entry.name()), serialized);
}
}));
} catch (UncheckedIOException | IOException ex) {
L.log(Level.WARNING, "Can't open asset bundle " + file, ex);
}
} else {
// load file directly
try (SerializedFileReader reader = new SerializedFileReader(file)) {
SerializedFile serialized = reader.read();
runSerializedFile(file, serialized);
} catch (IOException ex) {
L.log(Level.WARNING, "Can't open asset file " + file, ex);
}
}
}
Aggregations