/* * * pkg compression strat * * if compflag is set reserve chunkblockheader space in header based on sizeestimation * write file * go back to chunkblockheader, generate chunkheaders * allocate subblocks for chunks * compress subblocks * write chunkblockheaders. last action. * ez win * */ public void Compress(byte[] uncompressedData, int blockCount, int blockSize, int compFlag) { //131072 subblocksize //8 subblocks in one block = 1048576 //n blocks chunkBlocks.Clear(); compressedSize = 0; int dataOffset = 0; for (int j = 0; j < blockCount; j++) { int toCompress = blockSize; if (dataOffset + blockSize > uncompressedData.Length) { toCompress = uncompressedData.Length - dataOffset; } var blockBuffer = new byte[toCompress]; Array.ConstrainedCopy(uncompressedData, dataOffset, blockBuffer, 0, toCompress); var block = new ChunkBlock(); block.uncompressedDataSize = toCompress; block.uncompressedData = blockBuffer; //do it block.compressPackageFlags(compFlag); compressedSize += block.compressedSize; chunkBlocks.Add(block); dataOffset += toCompress; } }
public void Decompress(byte[] uncompressedData, int blockCount, BinaryReader reader, int compFlag) { int blockOffset = 0; chunkBlocks.Clear(); for (int j = 0; j < blockCount; ++j) { var block = new ChunkBlock(); block.compressedSize = reader.ReadInt32(); block.uncompressedDataSize = reader.ReadInt32(); chunkBlocks.Add(block); } foreach (ChunkBlock block in chunkBlocks) { block.compressedData = reader.ReadBytes(block.compressedSize); block.decompressPackageFlags(compFlag); Array.ConstrainedCopy(block.uncompressedData, 0, uncompressedData, blockOffset, block.uncompressedDataSize); blockOffset += block.uncompressedDataSize; //save memory block.uncompressedData = null; } }
/// <summary> /// Writes code for the given <paramref name="chunk"/>. /// </summary> /// <param name="chunk">The <see cref="ChunkBlock"/> to render.</param> /// <remarks> /// Tracks code mappings for all children while writing. /// </remarks> protected override void Visit(ChunkBlock chunk) { // Line mappings are captured in RenderCode(), not this method. _firstChild = true; Accept(chunk.Children); if (_firstChild) { // Attribute value was empty. Context.ErrorSink.OnError( chunk.Association.Start, RazorResources.TagHelpers_AttributeExpressionRequired, chunk.Association.Length); } }
void SetBlock(byte blockIndex) { var chunkManager = WorldManager.ChunkManager; var chunk = chunkManager.GetChunkByBlockPosition(BlockPosition); if (chunk == null) { throw new InvalidOperationException("Chunk not found: BlockPosition=" + BlockPosition); } var relativePosition = chunk.GetRelativeBlockPosition(BlockPosition); lastBlockIndex = chunk.GetBlockIndex(relativePosition); // 既存ブロックと同じならば処理せず、Undo 履歴にも残さない。 if (blockIndex == lastBlockIndex) { return; } chunk.SetBlockIndex(relativePosition, blockIndex); // メッシュ再構築。 chunkManager.RequestUpdateMesh(chunk, ChunkMeshUpdatePriority.High); // 影響を受ける隣接チャンクがあるならば、それらもメッシュ再構築。 var chunkBlock = new ChunkBlock(chunk, relativePosition); for (int i = 0; i < Side.Count; i++) { var neighborChunkBlock = chunkBlock.GetNeighbor(Side.Items[i]); if (neighborChunkBlock.Chunk != null && neighborChunkBlock.Chunk != chunkBlock.Chunk) { chunkManager.RequestUpdateMesh(neighborChunkBlock.Chunk, ChunkMeshUpdatePriority.High); } } }
private void getData(uint offset, uint length, Stream output) { if (compressed) { uint bytesLeft = length; for (int c = 0; c < chunks.Count; c++) { Chunk chunk = chunks[c]; if (chunk.uncomprOffset + chunk.uncomprSize <= offset) { continue; } uint startInChunk; if (offset < chunk.uncomprOffset) { startInChunk = 0; } else { startInChunk = offset - chunk.uncomprOffset; } uint bytesLeftInChunk = Math.Min(chunk.uncomprSize - startInChunk, bytesLeft); if (currentChunk != c) { if (chunkCache != null) { chunkCache.Close(); chunkCache.Dispose(); } chunkCache = new MemoryStream(); currentChunk = c; packageFile.JumpTo(chunk.comprOffset); uint blockTag = packageFile.ReadUInt32(); // block tag if (blockTag != packageTag) { throw new Exception("not match"); } uint blockSize = packageFile.ReadUInt32(); // max block size if (blockSize != maxBlockSize) { throw new Exception("not match"); } uint compressedChunkSize = packageFile.ReadUInt32(); // compressed chunk size uint uncompressedChunkSize = packageFile.ReadUInt32(); if (uncompressedChunkSize != chunk.uncomprSize) { throw new Exception("not match"); } uint blocksCount = (uncompressedChunkSize + maxBlockSize - 1) / maxBlockSize; if ((compressedChunkSize + SizeOfChunk + SizeOfChunkBlock * blocksCount) != chunk.comprSize) { throw new Exception("not match"); } List <ChunkBlock> blocks = new List <ChunkBlock>(); for (uint b = 0; b < blocksCount; b++) { ChunkBlock block = new ChunkBlock(); block.comprSize = packageFile.ReadUInt32(); block.uncomprSize = packageFile.ReadUInt32(); blocks.Add(block); } chunk.blocks = blocks; for (int b = 0; b < blocks.Count; b++) { ChunkBlock block = blocks[b]; block.compressedBuffer = packageFile.ReadToBuffer(block.comprSize); block.uncompressedBuffer = new byte[maxBlockSize * 2]; blocks[b] = block; } if (compressionType == CompressionType.LZO) { for (int b = 0; b < blocks.Count; b++) { uint dstLen; ChunkBlock block = blocks[b]; dstLen = LZO2Helper.LZO2.Decompress(block.compressedBuffer, block.comprSize, block.uncompressedBuffer); if (dstLen != block.uncomprSize) { throw new Exception("Decompressed data size not expected!"); } } } else { Parallel.For(0, blocks.Count, b => { uint dstLen = 0; ChunkBlock block = blocks[b]; if (compressionType == CompressionType.Zlib) { dstLen = ZlibHelper.Zlib.Decompress(block.compressedBuffer, block.comprSize, block.uncompressedBuffer); } if (dstLen != block.uncomprSize) { throw new Exception("Decompressed data size not expected!"); } }); } for (int b = 0; b < blocks.Count; b++) { chunkCache.Write(blocks[b].uncompressedBuffer, 0, (int)blocks[b].uncomprSize); } } chunkCache.JumpTo(startInChunk); output.WriteFromStream(chunkCache, bytesLeftInChunk); bytesLeft -= bytesLeftInChunk; if (bytesLeft == 0) { break; } } } else { packageFile.JumpTo(offset); output.WriteFromStream(packageFile, length); } }
public bool SaveToFile(bool forceZlib = false) { if (forceZlib && compressionType != CompressionType.Zlib) { modified = true; } if (packageFile.Length == 0 || !modified) { return(false); } MemoryStream tempOutput = new MemoryStream(); List <ExportEntry> sortedExports = exportsTable.OrderBy(s => s.dataOffset).ToList(); if (!compressed) { packageFile.SeekBegin(); tempOutput.WriteFromStream(packageFile, sortedExports[0].dataOffset); } else { packageData.SeekBegin(); tempOutput.WriteFromStream(packageData, packageData.Length); } for (int i = 0; i < exportsCount; i++) { ExportEntry export = sortedExports[i]; uint dataLeft; tempOutput.JumpTo(export.dataOffset); if (i + 1 == exportsCount) { dataLeft = exportsEndOffset - export.dataOffset - export.dataSize; } else { dataLeft = sortedExports[i + 1].dataOffset - export.dataOffset - export.dataSize; } if (export.updatedData) { string exportFile = packagePath + "-exports\\exportId-" + export.id; using (FileStream fs = new FileStream(exportFile, FileMode.Open, FileAccess.Read)) { tempOutput.WriteFromStream(fs, fs.Length); } export.updatedData = false; } else if (export.newData != null) { tempOutput.WriteFromBuffer(export.newData); } else { getData(export.dataOffset, export.dataSize, tempOutput); } tempOutput.WriteZeros(dataLeft); } if (exportsOffset > sortedExports[0].dataOffset) { if (compressed) // allowed only uncompressed { throw new Exception(); } exportsOffset = (uint)tempOutput.Position; saveExports(tempOutput); exportsEndOffset = (uint)tempOutput.Position; } else { tempOutput.JumpTo(exportsOffset); saveExports(tempOutput); } tempOutput.JumpTo(exportsEndOffset); if (namesOffset > sortedExports[0].dataOffset) { if (compressed) // allowed only uncompressed { throw new Exception(); } namesOffset = (uint)tempOutput.Position; saveNames(tempOutput, true); } else { saveNames(tempOutput); } if (importsOffset > sortedExports[0].dataOffset) { if (compressed) // allowed only uncompressed { throw new Exception(); } importsOffset = (uint)tempOutput.Position; saveImports(tempOutput, true); } else { saveImports(tempOutput); } if (namesOffset > sortedExports[0].dataOffset || importsOffset > sortedExports[0].dataOffset || exportsOffset > sortedExports[0].dataOffset) { tempOutput.SeekBegin(); tempOutput.Write(packageHeader, 0, packageHeader.Length); } packageFile.Close(); if (!memoryMode && Directory.Exists(packagePath + "-exports")) { Directory.Delete(packagePath + "-exports", true); } string filename = packageFile.Name; using (FileStream fs = new FileStream(filename, FileMode.Create, FileAccess.Write)) { if (fs == null) { throw new Exception("Failed to write to file: " + filename); } if (!compressed) { tempOutput.SeekBegin(); fs.WriteFromStream(tempOutput, tempOutput.Length); } else { if (chunks == null) { chunks = new List <Chunk>(); } chunks.Clear(); Chunk chunk = new Chunk(); chunk.uncomprSize = sortedExports[0].dataOffset - (uint)dataOffset; chunk.uncomprOffset = (uint)dataOffset; for (int i = 0; i < exportsCount; i++) { ExportEntry export = sortedExports[i]; uint dataSize; if (i + 1 == exportsCount) { dataSize = exportsEndOffset - export.dataOffset; } else { dataSize = sortedExports[i + 1].dataOffset - export.dataOffset; } if (chunk.uncomprSize + dataSize > maxChunkSize) { uint offset = chunk.uncomprOffset + chunk.uncomprSize; chunks.Add(chunk); chunk = new Chunk(); chunk.uncomprSize = dataSize; chunk.uncomprOffset = offset; } else { chunk.uncomprSize += dataSize; } } chunks.Add(chunk); if (forceZlib) { compressionType = CompressionType.Zlib; // override compression type to Zlib } fs.Write(packageHeader, 0, packageHeader.Length); fs.WriteUInt32((uint)compressionType); fs.WriteUInt32((uint)chunks.Count); uint chunksTableOffset = (uint)fs.Position; fs.Skip(SizeOfChunk * chunks.Count); // skip chunks table - filled later fs.WriteUInt32(someTag); if (version == packageFileVersionME2) { fs.WriteUInt32(0); // const 0 } saveExtraNames(fs); for (int c = 0; c < chunks.Count; c++) { chunk = chunks[c]; chunk.comprOffset = (uint)fs.Position; chunk.comprSize = 0; // filled later uint dataBlockLeft = chunk.uncomprSize; uint newNumBlocks = (chunk.uncomprSize + maxBlockSize - 1) / maxBlockSize; // skip blocks header and table - filled later fs.Seek(SizeOfChunk + SizeOfChunkBlock * newNumBlocks, SeekOrigin.Current); tempOutput.JumpTo(chunk.uncomprOffset); chunk.blocks = new List <ChunkBlock>(); for (int b = 0; b < newNumBlocks; b++) { ChunkBlock block = new ChunkBlock(); block.uncomprSize = Math.Min(maxBlockSize, dataBlockLeft); dataBlockLeft -= block.uncomprSize; block.uncompressedBuffer = tempOutput.ReadToBuffer(block.uncomprSize); chunk.blocks.Add(block); } if (compressionType == CompressionType.LZO) { for (int b = 0; b < newNumBlocks; b++) { ChunkBlock block = chunk.blocks[b]; block.compressedBuffer = LZO2Helper.LZO2.Compress(block.uncompressedBuffer); if (block.compressedBuffer.Length == 0) { throw new Exception("Compression failed!"); } block.comprSize = (uint)block.compressedBuffer.Length; chunk.blocks[b] = block; } } else { Parallel.For(0, chunk.blocks.Count, b => { ChunkBlock block = chunk.blocks[b]; if (compressionType == CompressionType.Zlib) { block.compressedBuffer = ZlibHelper.Zlib.Compress(block.uncompressedBuffer); } else { throw new Exception("Compression type not expected!"); } if (block.compressedBuffer.Length == 0) { throw new Exception("Compression failed!"); } block.comprSize = (uint)block.compressedBuffer.Length; chunk.blocks[b] = block; }); } for (int b = 0; b < newNumBlocks; b++) { ChunkBlock block = chunk.blocks[b]; fs.Write(block.compressedBuffer, 0, (int)block.comprSize); chunk.comprSize += block.comprSize; } chunks[c] = chunk; } for (int c = 0; c < chunks.Count; c++) { chunk = chunks[c]; fs.JumpTo(chunksTableOffset + c * SizeOfChunk); // jump to chunks table fs.WriteUInt32(chunk.uncomprOffset); fs.WriteUInt32(chunk.uncomprSize); fs.WriteUInt32(chunk.comprOffset); fs.WriteUInt32(chunk.comprSize + SizeOfChunk + SizeOfChunkBlock * (uint)chunk.blocks.Count); fs.JumpTo(chunk.comprOffset); // jump to blocks header fs.WriteUInt32(packageTag); fs.WriteUInt32(maxBlockSize); fs.WriteUInt32(chunk.comprSize); fs.WriteUInt32(chunk.uncomprSize); foreach (ChunkBlock block in chunk.blocks) { fs.WriteUInt32(block.comprSize); fs.WriteUInt32(block.uncomprSize); } } for (int c = 0; c < chunks.Count; c++) { chunk = chunks[c]; chunk.blocks.Clear(); chunk.blocks = null; } chunks.Clear(); chunks = null; } } tempOutput.Close(); tempOutput.Dispose(); return(true); }
public static byte[] CompressTexture(byte[] inputData, StorageTypes type) { using (MemoryStream ouputStream = new MemoryStream()) { uint compressedSize = 0; uint dataBlockLeft = (uint)inputData.Length; uint newNumBlocks = ((uint)inputData.Length + maxBlockSize - 1) / maxBlockSize; List <ChunkBlock> blocks = new List <ChunkBlock>(); using (MemoryStream inputStream = new MemoryStream(inputData)) { // skip blocks header and table - filled later ouputStream.Seek(SizeOfChunk + SizeOfChunkBlock * newNumBlocks, SeekOrigin.Begin); for (int b = 0; b < newNumBlocks; b++) { ChunkBlock block = new ChunkBlock(); block.uncomprSize = Math.Min(maxBlockSize, dataBlockLeft); dataBlockLeft -= block.uncomprSize; block.uncompressedBuffer = inputStream.ReadToBuffer(block.uncomprSize); blocks.Add(block); } } Parallel.For(0, blocks.Count, b => { ChunkBlock block = blocks[b]; if (type == StorageTypes.extLZO || type == StorageTypes.pccLZO) { block.compressedBuffer = LZO2Helper.LZO2.Compress(block.uncompressedBuffer); } else if (type == StorageTypes.extZlib || type == StorageTypes.pccZlib) { block.compressedBuffer = ZlibHelper.Zlib.Compress(block.uncompressedBuffer); } else { throw new Exception("Compression type not expected!"); } if (block.compressedBuffer.Length == 0) { throw new Exception("Compression failed!"); } block.comprSize = (uint)block.compressedBuffer.Length; blocks[b] = block; }); for (int b = 0; b < blocks.Count; b++) { ChunkBlock block = blocks[b]; ouputStream.Write(block.compressedBuffer, 0, (int)block.comprSize); compressedSize += block.comprSize; } ouputStream.SeekBegin(); ouputStream.WriteUInt32(textureTag); ouputStream.WriteUInt32(maxBlockSize); ouputStream.WriteUInt32(compressedSize); ouputStream.WriteInt32(inputData.Length); foreach (ChunkBlock block in blocks) { ouputStream.WriteUInt32(block.comprSize); ouputStream.WriteUInt32(block.uncomprSize); } return(ouputStream.ToArray()); } }
public static void DecompressTexture(byte[] DecompressedBuffer, MemoryStream stream, StorageTypes type, int uncompressedSize, int compressedSize) { uint blockTag = stream.ReadUInt32(); if (blockTag != textureTag) { throw new Exception("Texture tag wrong"); } uint blockSize = stream.ReadUInt32(); if (blockSize != maxBlockSize) { throw new Exception("Texture header broken"); } uint compressedChunkSize = stream.ReadUInt32(); uint uncompressedChunkSize = stream.ReadUInt32(); if (uncompressedChunkSize != uncompressedSize) { throw new Exception("Texture header broken"); } uint blocksCount = (uncompressedChunkSize + maxBlockSize - 1) / maxBlockSize; if ((compressedChunkSize + SizeOfChunk + SizeOfChunkBlock * blocksCount) != compressedSize) { throw new Exception("Texture header broken"); } var blocks = new List <ChunkBlock>(); for (uint b = 0; b < blocksCount; b++) { ChunkBlock block = new ChunkBlock { comprSize = stream.ReadUInt32(), uncomprSize = stream.ReadUInt32() }; blocks.Add(block); } for (int b = 0; b < blocks.Count; b++) { ChunkBlock block = blocks[b]; block.compressedBuffer = stream.ReadToBuffer(blocks[b].comprSize); block.uncompressedBuffer = new byte[maxBlockSize * 2]; blocks[b] = block; } Parallel.For(0, blocks.Count, b => { uint dstLen; ChunkBlock block = blocks[b]; if (type == StorageTypes.extLZO || type == StorageTypes.pccLZO) { dstLen = LZO2Helper.LZO2.Decompress(block.compressedBuffer, block.comprSize, block.uncompressedBuffer); } else if (type == StorageTypes.extZlib || type == StorageTypes.pccZlib) { dstLen = ZlibHelper.Zlib.Decompress(block.compressedBuffer, block.comprSize, block.uncompressedBuffer); } else { throw new Exception("Compression type not expected!"); } if (dstLen != block.uncomprSize) { throw new Exception("Decompressed data size not expected!"); } }); int dstPos = 0; for (int b = 0; b < blocks.Count; b++) { Buffer.BlockCopy(blocks[b].uncompressedBuffer, 0, DecompressedBuffer, dstPos, (int)blocks[b].uncomprSize); dstPos += (int)blocks[b].uncomprSize; } }
public void BuildMesh() { if (Mesh != null) { frontMeshBuilder.Clear(); } // We use a temporary empty var here in the case of this being ran on a seperate thread. // If this chunk was previously renderable, and is being updated, we don't want it to "flicker" // on the main thread while it is being updated. The main thread should just render the old mesh // until this is completed. bool isEmpty = true; for (int x = 0; x < HSIZE; x++) { for (int y = 0; y < VSIZE; y++) { for (int z = 0; z < HSIZE; z++) { // Grab data about the current block ChunkBlock data = blockData[z, y, x]; Block block = Blocks[z, y, x]; // If it's not air, lets draw! if (block != Block.AIR) { // Calculate the color of the block Color4 voxelColor = block.GetColor4(); // Determine which builder we'll be using VoxelMeshBuilder useBuilder = frontMeshBuilder; // Calculate the position of the block for local and global space. IndexPosition blockPos = new IndexPosition(x, y, z); Vector3 off = (blockPos * Block.CUBE_SIZE); // Get information about this block's neighbors. bool blockAbove, blockBelow, blockLeft, blockForward, blockBackward, blockRight; if (Mesh != null && !dirtyMask[z, y, x]) { // If this block was already calculated and isn't dirty, // we can simply pull the neighbor data from the chunkblock data. blockAbove = data.Up; blockBelow = data.Down; blockLeft = data.Left; blockForward = data.Front; blockBackward = data.Back; blockRight = data.Right; } else { // Search for each block in all 6 directions blockAbove = GetBlockSafe(x, y + 1, z).IsOpaqueTo(block); blockBelow = GetBlockSafe(x, y - 1, z).IsOpaqueTo(block); blockLeft = GetBlockSafe(x - 1, y, z).IsOpaqueTo(block); blockForward = GetBlockSafe(x, y, z + 1).IsOpaqueTo(block); blockBackward = GetBlockSafe(x, y, z - 1).IsOpaqueTo(block); blockRight = GetBlockSafe(x + 1, y, z).IsOpaqueTo(block); // Update the chunkblock data data.SetNeighbors(blockAbove, blockBelow, blockLeft, blockRight, blockForward, blockBackward); } // Only set this chunk to being non-empty if we are actually rendering something if (data.NeighborCount != 6) { isEmpty = false; } // Add each cube face if (!blockLeft) { useBuilder.AddLeft(block, blockPos, off, voxelColor); } if (!blockRight) { useBuilder.AddRight(block, blockPos, off, voxelColor); } if (!blockBackward) { useBuilder.AddBack(block, blockPos, off, voxelColor); } if (!blockForward) { useBuilder.AddFront(block, blockPos, off, voxelColor); } if (!blockAbove) { useBuilder.AddTop(block, blockPos, off, voxelColor); } if (!blockBelow) { useBuilder.AddBottom(block, blockPos, off, voxelColor); } } else { // Default air-blocks to zero so that they are // correctly updated when a block is place there later. data.NeighborCount = 0; } // Update the block data dirtyMask[z, y, x] = false; blockData[z, y, x] = data; } } } IsEmpty = isEmpty; // Swap Buffers VoxelMeshBuilder temp = frontMeshBuilder; frontMeshBuilder = backMeshBuilder; backMeshBuilder = temp; }
private void pCCXXXToolStripMenuItem_Click(object sender, EventArgs e) { OpenFileDialog d = new OpenFileDialog(); d.Filter = "ME3 XBox File(*.pcc)|*.pcc"; List <ChunkBlock> cb = new List <ChunkBlock>(); if (d.ShowDialog() == DialogResult.OK) { string loc = Path.GetDirectoryName(Application.ExecutablePath); File.Copy(d.FileName, loc + "\\exec\\temp.dat", true); FileStream fs = new FileStream(loc + "\\exec\\temp.dat", FileMode.Open, FileAccess.Read); int block = 0x20000; int count = (int)fs.Length / block; rtb1.Text = "Loading file: " + d.FileName + "\n"; if (fs.Length % block != 0) { count++; } int pos = 0; int size = block; byte[] buff; if (File.Exists(loc + "\\exec\\tmpout.dat")) { File.Delete(loc + "\\exec\\tmpout.dat"); } FileStream fout = new FileStream(loc + "\\exec\\tmpout.dat", FileMode.Create, FileAccess.Write); for (int i = 0; i < count; i++) { if (pos + size > fs.Length) { size = (int)fs.Length - pos; } FileStream fs2 = new FileStream(loc + "\\exec\\tmp.dat", FileMode.Create, FileAccess.Write); for (int j = 0; j < size; j++) { fs2.WriteByte((byte)fs.ReadByte()); } fs2.Close(); fs2 = new FileStream(loc + "\\exec\\Convert.bms", FileMode.Create, FileAccess.Write); buff = StrToBuf("log \"out.bin\" 0 0" + (char)0xD + (char)0xA); fs2.Write(buff, 0, buff.Length); buff = StrToBuf("ComType xmemlzx_compress" + (char)0xD + (char)0xA); fs2.Write(buff, 0, buff.Length); buff = StrToBuf("Clog \"out.bin\" 0 " + size.ToString() + " 10000000" + (char)0xD + (char)0xA); fs2.Write(buff, 0, buff.Length); buff = StrToBuf("Print \"Compressing Block #" + i.ToString() + "/" + count.ToString() + "\"..."); fs2.Write(buff, 0, buff.Length); fs2.Close(); System.Diagnostics.ProcessStartInfo procStartInfo = new System.Diagnostics.ProcessStartInfo(loc + "\\exec\\quickbms.exe", "-o Convert.bms tmp.dat"); procStartInfo.WorkingDirectory = Path.GetDirectoryName(loc + "\\exec\\"); procStartInfo.RedirectStandardOutput = true; procStartInfo.UseShellExecute = false; procStartInfo.CreateNoWindow = true; using (System.Diagnostics.Process process = System.Diagnostics.Process.Start(procStartInfo)) { using (StreamReader reader = process.StandardOutput) { string result = reader.ReadToEnd(); rtb1.Text += result; rtb1.SelectionStart = rtb1.Text.Length; rtb1.ScrollToCaret(); Application.DoEvents(); } } fs2 = new FileStream(loc + "\\exec\\out.bin", FileMode.Open, FileAccess.Read); for (int j = 0; j < fs2.Length; j++) { fout.WriteByte((byte)fs2.ReadByte()); } buff = new byte[4]; fout.Write(buff, 0, 4); ChunkBlock t = new ChunkBlock(); t.sizeUC = size; t.sizeC = (int)fs2.Length + 4; cb.Add(t); fs2.Close(); pos += size; } int fullsize = (int)fout.Length; fout.Close(); rtb1.Text += "\nCombining Chunks to xxx file..."; rtb1.SelectionStart = rtb1.Text.Length; rtb1.ScrollToCaret(); bool isLittle = BitConverter.IsLittleEndian; BitConverter.IsLittleEndian = true; fout = new FileStream(Path.GetDirectoryName(d.FileName) + "\\" + Path.GetFileNameWithoutExtension(d.FileName) + ".xxx", FileMode.Create, FileAccess.Write); buff = BitConverter.GetBytes(0x9E2A83C1); fout.Write(buff, 0, 4); buff = BitConverter.GetBytes(0x00020000); fout.Write(buff, 0, 4); buff = BitConverter.GetBytes(fullsize); fout.Write(buff, 0, 4); buff = BitConverter.GetBytes(fs.Length); fout.Write(buff, 0, 4); fs.Close(); for (int i = 0; i < cb.Count; i++) { buff = BitConverter.GetBytes(cb[i].sizeC); fout.Write(buff, 0, 4); buff = BitConverter.GetBytes(cb[i].sizeUC); fout.Write(buff, 0, 4); } fs = new FileStream(loc + "\\exec\\tmpout.dat", FileMode.Open, FileAccess.Read); for (int i = 0; i < fs.Length; i++) { fout.WriteByte((byte)fs.ReadByte()); } fout.Close(); fs.Close(); if (File.Exists(loc + "\\exec\\tmp.dat")) { File.Delete(loc + "\\exec\\tmp.dat"); } if (File.Exists(loc + "\\exec\\tmpout.dat")) { File.Delete(loc + "\\exec\\tmpout.dat"); } if (File.Exists(loc + "\\exec\\temp.dat")) { File.Delete(loc + "\\exec\\temp.dat"); } if (File.Exists(loc + "\\exec\\Convert.bms")) { File.Delete(loc + "\\exec\\Convert.bms"); } if (File.Exists(loc + "\\exec\\out.bin")) { File.Delete(loc + "\\exec\\out.bin"); } rtb1.Text += "\nFile: " + Path.GetDirectoryName(d.FileName) + "\\" + Path.GetFileNameWithoutExtension(d.FileName) + ".xxx written to disk."; rtb1.SelectionStart = rtb1.Text.Length; rtb1.ScrollToCaret(); BitConverter.IsLittleEndian = isLittle; } }
public byte[] getRawTFCComp(uint pos) { MemoryStream ret = new MemoryStream(); if (!File.Exists(filename)) { return(ret.ToArray()); } FileStream fs = new FileStream(filename, FileMode.Open, FileAccess.Read); if (pos > fs.Length) { fs.Close(); return(ret.ToArray()); } fs.Seek(pos, SeekOrigin.Begin); ChunkHeader ch = new ChunkHeader(); List <ChunkBlock> cb = new List <ChunkBlock>(); byte[] buff = new byte[4]; fs.Read(buff, 0, 4); uint magic = BitConverter.ToUInt32(buff, 0); if (magic == 0x9E2A83C1) { ch.magic = magic; fs.Read(buff, 0, 4); ch.blocksize = BitConverter.ToUInt32(buff, 0); fs.Read(buff, 0, 4); ch.compsize = BitConverter.ToUInt32(buff, 0); fs.Read(buff, 0, 4); ch.uncompsize = BitConverter.ToUInt32(buff, 0); } int n = (int)(ch.uncompsize / ch.blocksize); if (ch.uncompsize < ch.blocksize) { n = 1; } for (int i = 0; i < n; i++) { ChunkBlock t = new ChunkBlock(); fs.Read(buff, 0, 4); t.compsize = BitConverter.ToUInt32(buff, 0); fs.Read(buff, 0, 4); t.uncompsize = BitConverter.ToUInt32(buff, 0); cb.Add(t); } string loc = Path.GetDirectoryName(Application.ExecutablePath); for (int i = 0; i < n; i++) { if (File.Exists(loc + "\\exec\\temp.dat")) { File.Delete(loc + "\\exec\\temp.dat"); } if (File.Exists(loc + "\\exec\\out.dat")) { File.Delete(loc + "\\exec\\out.dat"); } FileStream fs2 = new FileStream(loc + "\\exec\\temp.dat", FileMode.Create, FileAccess.Write); for (int j = 0; j < cb[i].compsize; j++) { fs2.WriteByte((byte)fs.ReadByte()); } fs2.Close(); RunShell(loc + "\\exec\\zlibber.exe", "-sdc temp.dat out.dat"); fs2 = new FileStream(loc + "\\exec\\out.dat", FileMode.Open, FileAccess.Read); buff = new byte[fs2.Length]; for (int j = 0; j < fs2.Length; j++) { buff[j] = (byte)fs2.ReadByte(); } fs2.Close(); StreamAppend(ret, buff); } fs.Close(); return(ret.ToArray()); }
public byte[] getRawTFCComp(uint pos) { MemoryStream ret = new MemoryStream(); if (!File.Exists(filename)) return ret.ToArray(); FileStream fs = new FileStream(filename, FileMode.Open, FileAccess.Read); if (pos > fs.Length) { fs.Close(); return ret.ToArray(); } fs.Seek(pos, SeekOrigin.Begin); ChunkHeader ch = new ChunkHeader(); List<ChunkBlock> cb = new List<ChunkBlock>(); byte[] buff = new byte[4]; fs.Read(buff, 0, 4); uint magic = BitConverter.ToUInt32(buff, 0); if (magic == 0x9E2A83C1) { ch.magic = magic; fs.Read(buff, 0, 4); ch.blocksize = BitConverter.ToUInt32(buff, 0); fs.Read(buff, 0, 4); ch.compsize = BitConverter.ToUInt32(buff, 0); fs.Read(buff, 0, 4); ch.uncompsize = BitConverter.ToUInt32(buff, 0); } int n = (int)(ch.uncompsize / ch.blocksize); if (ch.uncompsize < ch.blocksize) n = 1; for (int i = 0; i < n; i++) { ChunkBlock t = new ChunkBlock(); fs.Read(buff, 0, 4); t.compsize = BitConverter.ToUInt32(buff, 0); fs.Read(buff, 0, 4); t.uncompsize = BitConverter.ToUInt32(buff, 0); cb.Add(t); } string loc = Path.GetDirectoryName(Application.ExecutablePath); for (int i = 0; i < n; i++) { if (File.Exists(loc + "\\exec\\temp.dat")) File.Delete(loc + "\\exec\\temp.dat"); if (File.Exists(loc + "\\exec\\out.dat")) File.Delete(loc + "\\exec\\out.dat"); FileStream fs2 = new FileStream(loc + "\\exec\\temp.dat", FileMode.Create, FileAccess.Write); for (int j = 0; j < cb[i].compsize; j++) fs2.WriteByte((byte)fs.ReadByte()); fs2.Close(); RunShell(loc + "\\exec\\zlibber.exe", "-sdc temp.dat out.dat"); fs2 = new FileStream(loc + "\\exec\\out.dat", FileMode.Open, FileAccess.Read); buff = new byte[fs2.Length]; for (int j = 0; j < fs2.Length; j++) buff[j] = (byte)fs2.ReadByte(); fs2.Close(); StreamAppend(ret, buff); } fs.Close(); return ret.ToArray(); }
public byte[] makeRawTFCComp(byte[] input) { MemoryStream ms = new MemoryStream(); byte[] buff = BitConverter.GetBytes(0x9E2A83C1); ms.Write(buff, 0, 4); buff = BitConverter.GetBytes((Int32)0x20000); ms.Write(buff, 0, 4); int n = input.Length / 0x20000; if (input.Length < 0x20000) n = 1; int pos = 0; string loc = Path.GetDirectoryName(Application.ExecutablePath); if (File.Exists(loc + "\\exec\\temp.dat")) File.Delete(loc + "\\exec\\temp.dat"); FileStream fs = new FileStream(loc + "\\exec\\temp.dat", FileMode.Create, FileAccess.Write); List<ChunkBlock> cb = new List<ChunkBlock>(); for (int i = 0; i < n; i++) { int len = 0x20000; if (input.Length - pos < 0x20000) len = input.Length - pos; if (File.Exists(loc + "\\exec\\out0.dat")) File.Delete(loc + "\\exec\\out0.dat"); if (File.Exists(loc + "\\exec\\out1.dat")) File.Delete(loc + "\\exec\\out1.dat"); FileStream fs2 = new FileStream(loc + "\\exec\\out0.dat",FileMode.Create,FileAccess.Write); for (int j = pos; j<pos+len; j++) fs2.WriteByte((byte)input[j]); fs2.Close(); RunShell(loc + "\\exec\\zlibber", "-sc out0.dat out1.dat"); fs2 = new FileStream(loc + "\\exec\\out1.dat",FileMode.Open,FileAccess.Read); for (int j = 0; j < fs2.Length; j++) fs.WriteByte((byte)fs2.ReadByte()); ChunkBlock t = new ChunkBlock(); t.compsize = (uint)fs2.Length; t.uncompsize = (uint)len; cb.Add(t); fs2.Close(); pos += 0x20000; } buff = BitConverter.GetBytes((Int32)fs.Length); ms.Write(buff, 0, 4); buff = BitConverter.GetBytes((Int32)input.Length); ms.Write(buff, 0, 4); for (int i = 0; i < n; i++) { buff = BitConverter.GetBytes((Int32)cb[i].compsize); ms.Write(buff, 0, 4); buff = BitConverter.GetBytes((Int32)cb[i].uncompsize); ms.Write(buff, 0, 4); } fs.Close(); fs = new FileStream(loc + "\\exec\\temp.dat", FileMode.Open, FileAccess.Read); for (int i = 0; i < fs.Length; i++) ms.WriteByte((byte)fs.ReadByte()); fs.Close(); if (File.Exists(loc + "\\exec\\temp.dat")) File.Delete(loc + "\\exec\\temp.dat"); if (File.Exists(loc + "\\exec\\out0.dat")) File.Delete(loc + "\\exec\\out0.dat"); if (File.Exists(loc + "\\exec\\out1.dat")) File.Delete(loc + "\\exec\\out1.dat"); return ms.ToArray(); }
protected override void Visit(ChunkBlock chunk) { Accept(chunk.Children); }
public byte[] makeRawTFCComp(byte[] input) { MemoryStream ms = new MemoryStream(); byte[] buff = BitConverter.GetBytes(0x9E2A83C1); ms.Write(buff, 0, 4); buff = BitConverter.GetBytes((Int32)0x20000); ms.Write(buff, 0, 4); int n = input.Length / 0x20000; if (input.Length < 0x20000) { n = 1; } int pos = 0; string loc = Path.GetDirectoryName(Application.ExecutablePath); if (File.Exists(loc + "\\exec\\temp.dat")) { File.Delete(loc + "\\exec\\temp.dat"); } FileStream fs = new FileStream(loc + "\\exec\\temp.dat", FileMode.Create, FileAccess.Write); List <ChunkBlock> cb = new List <ChunkBlock>(); for (int i = 0; i < n; i++) { int len = 0x20000; if (input.Length - pos < 0x20000) { len = input.Length - pos; } if (File.Exists(loc + "\\exec\\out0.dat")) { File.Delete(loc + "\\exec\\out0.dat"); } if (File.Exists(loc + "\\exec\\out1.dat")) { File.Delete(loc + "\\exec\\out1.dat"); } FileStream fs2 = new FileStream(loc + "\\exec\\out0.dat", FileMode.Create, FileAccess.Write); for (int j = pos; j < pos + len; j++) { fs2.WriteByte((byte)input[j]); } fs2.Close(); RunShell(loc + "\\exec\\zlibber", "-sc out0.dat out1.dat"); fs2 = new FileStream(loc + "\\exec\\out1.dat", FileMode.Open, FileAccess.Read); for (int j = 0; j < fs2.Length; j++) { fs.WriteByte((byte)fs2.ReadByte()); } ChunkBlock t = new ChunkBlock(); t.compsize = (uint)fs2.Length; t.uncompsize = (uint)len; cb.Add(t); fs2.Close(); pos += 0x20000; } buff = BitConverter.GetBytes((Int32)fs.Length); ms.Write(buff, 0, 4); buff = BitConverter.GetBytes((Int32)input.Length); ms.Write(buff, 0, 4); for (int i = 0; i < n; i++) { buff = BitConverter.GetBytes((Int32)cb[i].compsize); ms.Write(buff, 0, 4); buff = BitConverter.GetBytes((Int32)cb[i].uncompsize); ms.Write(buff, 0, 4); } fs.Close(); fs = new FileStream(loc + "\\exec\\temp.dat", FileMode.Open, FileAccess.Read); for (int i = 0; i < fs.Length; i++) { ms.WriteByte((byte)fs.ReadByte()); } fs.Close(); if (File.Exists(loc + "\\exec\\temp.dat")) { File.Delete(loc + "\\exec\\temp.dat"); } if (File.Exists(loc + "\\exec\\out0.dat")) { File.Delete(loc + "\\exec\\out0.dat"); } if (File.Exists(loc + "\\exec\\out1.dat")) { File.Delete(loc + "\\exec\\out1.dat"); } return(ms.ToArray()); }
protected override void Visit(ChunkBlock chunk) { }
private void pCCXXXToolStripMenuItem_Click(object sender, EventArgs e) { OpenFileDialog d = new OpenFileDialog(); d.Filter = "ME3 XBox File(*.pcc)|*.pcc"; List<ChunkBlock> cb = new List<ChunkBlock>(); if (d.ShowDialog() == DialogResult.OK) { string loc = Path.GetDirectoryName(Application.ExecutablePath); File.Copy(d.FileName, loc + "\\exec\\temp.dat", true); FileStream fs = new FileStream(loc + "\\exec\\temp.dat", FileMode.Open, FileAccess.Read); int block = 0x20000; int count = (int)fs.Length / block; rtb1.Text = "Loading file: " + d.FileName + "\n"; if (fs.Length % block != 0) count++; int pos = 0; int size = block; byte[] buff; if (File.Exists(loc + "\\exec\\tmpout.dat")) File.Delete(loc + "\\exec\\tmpout.dat"); FileStream fout = new FileStream(loc + "\\exec\\tmpout.dat", FileMode.Create, FileAccess.Write); for (int i = 0; i < count; i++) { if (pos + size > fs.Length) size = (int)fs.Length - pos; FileStream fs2 = new FileStream(loc + "\\exec\\tmp.dat", FileMode.Create, FileAccess.Write); for (int j = 0; j < size; j++) fs2.WriteByte((byte)fs.ReadByte()); fs2.Close(); fs2 = new FileStream(loc + "\\exec\\Convert.bms", FileMode.Create, FileAccess.Write); buff = StrToBuf("log \"out.bin\" 0 0" +(char)0xD + (char) 0xA); fs2.Write(buff, 0, buff.Length); buff = StrToBuf("ComType xmemlzx_compress" + (char)0xD + (char)0xA); fs2.Write(buff, 0, buff.Length); buff = StrToBuf("Clog \"out.bin\" 0 " + size.ToString() + " 10000000" + (char)0xD + (char)0xA); fs2.Write(buff, 0, buff.Length); buff = StrToBuf("Print \"Compressing Block #" + i.ToString() + "/" + count.ToString() + "\"..."); fs2.Write(buff, 0, buff.Length); fs2.Close(); System.Diagnostics.ProcessStartInfo procStartInfo = new System.Diagnostics.ProcessStartInfo(loc + "\\exec\\quickbms.exe", "-o Convert.bms tmp.dat"); procStartInfo.WorkingDirectory = Path.GetDirectoryName(loc + "\\exec\\"); procStartInfo.RedirectStandardOutput = true; procStartInfo.UseShellExecute = false; procStartInfo.CreateNoWindow = true; using (System.Diagnostics.Process process = System.Diagnostics.Process.Start(procStartInfo)) { using (StreamReader reader = process.StandardOutput) { string result = reader.ReadToEnd(); rtb1.Text += result; rtb1.SelectionStart = rtb1.Text.Length; rtb1.ScrollToCaret(); Application.DoEvents(); } } fs2 = new FileStream(loc + "\\exec\\out.bin", FileMode.Open, FileAccess.Read); for (int j = 0; j < fs2.Length; j++) fout.WriteByte((byte)fs2.ReadByte()); buff = new byte[4]; fout.Write(buff, 0, 4); ChunkBlock t = new ChunkBlock(); t.sizeUC = size; t.sizeC = (int)fs2.Length + 4; cb.Add(t); fs2.Close(); pos += size; } int fullsize = (int)fout.Length; fout.Close(); rtb1.Text += "\nCombining Chunks to xxx file..."; rtb1.SelectionStart = rtb1.Text.Length; rtb1.ScrollToCaret(); bool isLittle = BitConverter.IsLittleEndian; BitConverter.IsLittleEndian = true; fout = new FileStream(Path.GetDirectoryName(d.FileName) + "\\" + Path.GetFileNameWithoutExtension(d.FileName) + ".xxx", FileMode.Create, FileAccess.Write); buff = BitConverter.GetBytes(0x9E2A83C1); fout.Write(buff, 0, 4); buff = BitConverter.GetBytes(0x00020000); fout.Write(buff, 0, 4); buff = BitConverter.GetBytes(fullsize); fout.Write(buff, 0, 4); buff = BitConverter.GetBytes(fs.Length); fout.Write(buff, 0, 4); fs.Close(); for (int i = 0; i < cb.Count; i++) { buff = BitConverter.GetBytes(cb[i].sizeC); fout.Write(buff, 0, 4); buff = BitConverter.GetBytes(cb[i].sizeUC); fout.Write(buff, 0, 4); } fs = new FileStream(loc + "\\exec\\tmpout.dat", FileMode.Open, FileAccess.Read); for(int i=0;i<fs.Length ;i++) fout.WriteByte((byte)fs.ReadByte()); fout.Close(); fs.Close(); if (File.Exists(loc + "\\exec\\tmp.dat")) File.Delete(loc + "\\exec\\tmp.dat"); if (File.Exists(loc + "\\exec\\tmpout.dat")) File.Delete(loc + "\\exec\\tmpout.dat"); if (File.Exists(loc + "\\exec\\temp.dat")) File.Delete(loc + "\\exec\\temp.dat"); if (File.Exists(loc + "\\exec\\Convert.bms")) File.Delete(loc + "\\exec\\Convert.bms"); if (File.Exists(loc + "\\exec\\out.bin")) File.Delete(loc + "\\exec\\out.bin"); rtb1.Text += "\nFile: " + Path.GetDirectoryName(d.FileName) + "\\" + Path.GetFileNameWithoutExtension(d.FileName) + ".xxx written to disk."; rtb1.SelectionStart = rtb1.Text.Length; rtb1.ScrollToCaret(); BitConverter.IsLittleEndian = isLittle; } }