Ejemplo n.º 1
0
        internal override void Write(BinaryWriter writer)
        {
            // Save the start position to calculate the filesize and
            // to write out the header after we know where all the structure offsets are
            Stream stream       = writer.BaseStream;
            int    posFileStart = (int)stream.Position;

            stream.Seek(Spr4Header.SIZE, SeekOrigin.Current);

            // Create initial header and tables
            Spr4Header header = new Spr4Header(TextureCount, KeyFrameCount);

            TypePointerTable[] keyFramePointerTable = new TypePointerTable[header.numKeyFrames];
            TypePointerTable[] texturePointerTable  = new TypePointerTable[header.numTextures];

            // Set the pointer table offsets and seek past the entries
            // as the entries will be written later
            header.texturePointerTableOffset = (int)(stream.Position - posFileStart);
            stream.Seek(TypePointerTable.SIZE * header.numTextures, SeekOrigin.Current);

            header.keyFramePointerTableOffset = (int)(stream.Position - posFileStart);
            stream.Seek(TypePointerTable.SIZE * header.numKeyFrames, SeekOrigin.Current);

            // Write out the keyframe data and fill up the pointer table
            for (int i = 0; i < header.numKeyFrames; i++)
            {
                writer.AlignPosition(16);
                keyFramePointerTable[i].offset = (int)(stream.Position - posFileStart);
                mKeyFrames[i].Write(writer);
            }

            writer.Seek(16, SeekOrigin.Current);
            writer.AlignPosition(16);

            // Write out the texture data and fill up the pointer table
            for (int i = 0; i < header.numTextures; i++)
            {
                texturePointerTable[i].offset = (int)(stream.Position - posFileStart);
                mTextures[i].Write(writer);
                writer.Seek(16, SeekOrigin.Current);
            }

            // Save the end position
            long posFileEnd = stream.Position;

            // Seek back to the tables and write out the tables
            stream.Seek(posFileStart + header.texturePointerTableOffset, SeekOrigin.Begin);
            stream.WriteStructures(texturePointerTable, header.numTextures);

            stream.Seek(posFileStart + header.keyFramePointerTableOffset, SeekOrigin.Begin);
            stream.WriteStructures(keyFramePointerTable, header.numKeyFrames);

            // Seek back to the file and write out the header with
            // the offsets to the structures in the file
            writer.BaseStream.Seek(posFileStart, SeekOrigin.Begin);
            writer.BaseStream.WriteStructure(header);

            // Set the file pointer back to the end of the file as expected
            writer.BaseStream.Seek(posFileEnd, SeekOrigin.Begin);
        }
Ejemplo n.º 2
0
        public byte[] Repack(string baseDir, string lbName, string srcDir, string patchDir, List <SubItem> subItems)
        {
            byte[] dst;
            this.Load(IOHelper.PathCombine(srcDir, lbName));
            using (MemoryStream dstStream = new MemoryStream())
            {
                using (BinaryWriter bw = new BinaryWriter(dstStream))
                {
                    bw.Seek(0, SeekOrigin.Begin);
                    for (int i = 0; i < subItems.Count; i++)
                    {
                        SubItem vItem = subItems[i];
                        byte[]  vDataBytes;
                        if (File.Exists(IOHelper.PathCombine(patchDir, baseDir, vItem.FileName)))
                        {
                            //如果存在补丁文件,从补丁目录读取并压缩数据
                            vDataBytes = File.ReadAllBytes(IOHelper.PathCombine(patchDir, baseDir, vItem.FileName));
                        }
                        else
                        {
                            //如果不存在补丁文件,从原始目录读取
                            vDataBytes = File.ReadAllBytes(IOHelper.PathCombine(srcDir, baseDir, vItem.FileName));
                        }
                        if ((vItem.NeedReCompress == true) && (vItem.IsCompressed == true))
                        {
                            byte[] compressDataBytes;
                            int    compressLenght = 0;
                            LBC.Compress(vDataBytes, out compressDataBytes, out compressLenght);
                            bw.Write((int)vItem.FileID);
                            bw.Write((int)compressLenght + 0x10);
                            bw.Write((uint)vItem.ExtMagic);
                            bw.Write((int)vDataBytes.Length);
                            bw.Write(compressDataBytes);
                            bw.AlignPosition(0x40);
                        }

                        else if ((vItem.NeedReCompress == false) && (vItem.IsCompressed == true))
                        {
                            bw.Write(vDataBytes);
                            bw.AlignPosition(0x40);
                        }
                        else
                        {
                            bw.Write(vDataBytes);
                            bw.AlignPosition(0x40);
                        }
                    }
                    bw.Write((int)0xff);
                    bw.Write((int)0x10);
                    bw.Write((uint)0x30444e45);
                    bw.Write((int)0);
                    bw.Write(Enumerable.Repeat((byte)0, 0x30).ToArray());
                    dst = dstStream.ToArray();
                }
            }

            return(dst);
        }
Ejemplo n.º 3
0
        internal override void Write(BinaryWriter writer)
        {
            // Save the position of the file in the stream
            long posFileStart = writer.GetPosition();

            // Precalculate the first offset
            long posPrevDataEnd = (Entries.Count) * BvpEntry.SIZE;

            // Write the entry table
            for (int i = 0; i < Entries.Count; i++)
            {
                // The offset is the position where the last data write ended, aligned to the 16 byte boundary
                Entries[i].FileDataOffset = (int)AlignmentHelper.Align(posPrevDataEnd, 16);

                // Write table entry
                Entries[i].WriteEntryHeader(writer);

                // Write data at offset
                writer.Write(Entries[i].Data, posFileStart + Entries[i].FileDataOffset);

                // Update the previous data end position
                posPrevDataEnd = Entries[i].FileDataOffset + Entries[i].DataLength;
            }

            // Seek to the last data write position, and align the file to 64 bytes
            writer.BaseStream.Seek(posPrevDataEnd, SeekOrigin.Begin);
            writer.AlignPosition(32);
        }
Ejemplo n.º 4
0
        // Methods
        internal void InternalWrite(BinaryWriter writer)
        {
            int size = GetSize();

            writer.Write(size);
            writer.Write(mNumAssignedFrames);
            writer.Write(mType);

            for (int i = 0; i < mNumAssignedFrames; i++)
            {
                writer.Write(mAssignedFrameIndices[i]);
            }

            writer.AlignPosition(4);

            for (int i = 0; i < mNumAssignedFrames; i++)
            {
                switch (mType)
                {
                case 0x04:
                {
                    for (int j = 0; j < 2; j++)
                    {
                        writer.Write((ushort)(mBoneKeyData[i][j] * FIXED_POINT));
                    }
                }

                break;

                case 0x08:
                {
                    for (int j = 0; j < 4; j++)
                    {
                        writer.Write((ushort)(mBoneKeyData[i][j] * FIXED_POINT));
                    }
                }

                break;

                case 0x0C:
                {
                    for (int j = 0; j < 3; j++)
                    {
                        writer.Write(mBoneKeyData[i][j]);
                    }
                }

                break;

                default:
                    break;
                }
            }
        }
Ejemplo n.º 5
0
        internal void InternalWrite(BinaryWriter writer)
        {
            writer.WriteStructure(mHeader);

            for (int i = 0; i < mHeader.entryCount; i++)
            {
                mSubEntries[i].InternalWrite(writer);
            }

            writer.AlignPosition(16);

            for (int i = 0; i < mHeader.entryCount; i++)
            {
                if (i > 1 && mSubEntries[i].Flags.HasFlagUnchecked(RecordFlags.DirectoryRecord))
                {
                    mSubEntries[i].DirectoryListing.InternalWrite(writer);
                }
            }
        }
Ejemplo n.º 6
0
        // Internal Methods
        internal override void Write(BinaryWriter writer)
        {
            int posFileStart = (int)writer.BaseStream.Position;

            // Seek past chunk header
            writer.BaseStream.Seek(HEADER_SIZE + 4, SeekOrigin.Current);

            // Seek past texture pack header
            writer.BaseStream.Seek(TextureCount * sizeof(int), SeekOrigin.Current);

            int[] texturePointerTable = new int[TextureCount];

            // Write texture data
            for (int i = 0; i < TextureCount; i++)
            {
                writer.AlignPosition(64);
                texturePointerTable[i] = (int)(writer.BaseStream.Position - posFileStart);
                mTextures[i].Write(writer);
            }

            // Calculate length
            long posFileEnd = writer.BaseStream.Position;
            int  length     = (int)(posFileEnd - posFileStart);

            // Write header
            writer.BaseStream.Seek(posFileStart, SeekOrigin.Begin);
            writer.Write(FLAG);
            writer.Write((short)0); // userID
            writer.Write(length);
            writer.WriteCString(TAG, 4);
            writer.Write(0);
            writer.Write(TextureCount);

            // Write pointer table
            writer.Write(texturePointerTable);

            // Seek to end
            writer.BaseStream.Seek(posFileEnd, SeekOrigin.Begin);
        }
Ejemplo n.º 7
0
 public static void WriteCStringAligned(this BinaryWriter writer, string value)
 {
     writer.Write(_sjisEncoding.GetBytes(value));
     writer.AlignPosition(4);
 }
Ejemplo n.º 8
0
        // Methods
        internal override void Write(BinaryWriter writer)
        {
            // Skip header
            long posFileStart = (int)writer.BaseStream.Position;

            writer.Seek(MT00Header.SIZE, SeekOrigin.Current);

            MT00Header header = new MT00Header(AnimationCount, KeyCount);

            // Create address list for reloc table
            List <int> addressList = new List <int>();

            // Calculate size of key info table & anim pointer table offset
            int keyInfoTableSize = header.numKeys * AbKeyInfo.SIZE;

            header.animPointerTableOffset = (int)(((writer.GetPosition() + keyInfoTableSize) - DATA_START_ADDRESS) - posFileStart);

            addressList.Add((int)(writer.GetPosition() - 4 - posFileStart)); // animPointerTableOffset

            // Write key info
            for (int i = 0; i < mAnimKeyInfo.Length; i++)
            {
                writer.Write((ushort)mAnimKeyInfo[i].KeyType);
                writer.Write(mAnimKeyInfo[i].UnkMorph);
                writer.Write(mAnimKeyInfo[i].BoneIndex);
            }

            // Calculate anim pointer table size
            long posAnimPointerTable  = writer.GetPosition();
            int  animPointerTableSize = header.numAnims * sizeof(int);
            int  animPointerBase      = (int)posAnimPointerTable + animPointerTableSize;

            // Write anims
            int[] animPointers = new int[header.numAnims];
            for (int i = 0; i < animPointers.Length; i++)
            {
                if (mAnims[i] == null)
                {
                    animPointers[i] = 0;
                }
                else
                {
                    animPointers[i] = (int)((animPointerBase - DATA_START_ADDRESS) - posFileStart);

                    writer.Seek(animPointerBase, SeekOrigin.Begin);
                    mAnims[i].Write(writer);
                    animPointerBase = (int)writer.GetPosition();
                }
            }

            // Write pointer table
            writer.Seek(posAnimPointerTable, SeekOrigin.Begin);
            for (int i = 0; i < animPointers.Length; i++)
            {
                if (mAnims[i] != null)
                {
                    addressList.Add((int)(writer.GetPosition() - posFileStart));
                    writer.Write(animPointers[i]);
                }
            }

            writer.Seek(animPointerBase, SeekOrigin.Begin);

            // Calculate address reloc table values
            byte[] addressRelocTable = PointerRelocationTableCompression.Compress(addressList, DATA_START_ADDRESS);
            header.addressRelocTableSize   = addressRelocTable.Length;
            header.addressRelocTableOffset = (int)((writer.GetPosition() - DATA_START_ADDRESS) - posFileStart);

            // Write address reloc table
            writer.Write(addressRelocTable);

            long posFileEnd = writer.GetPosition();

            // Calculate length
            header.length = (int)(posFileEnd - posFileStart);

            // Write header
            writer.Seek(posFileStart, SeekOrigin.Begin);
            writer.WriteStructure(header);

            writer.BaseStream.Seek(posFileEnd, SeekOrigin.Begin);
            writer.AlignPosition(64);
        }
        public void Repack(string srcFolder, string patchFolder, string importFolder)
        {
            Logger.Print("正在读取索引数据");
            DDTFileTable table = JsonHelper.Deserialize <DDTFileTable>(File.ReadAllText("./dds3_table.json", Encoding.UTF8));

            this.GetEntry();
            Logger.Print("正在复制package");
            if (File.Exists(Path.Combine(importFolder, Path.GetFileName(this.ImgName))))
            {
                File.Delete(Path.Combine(importFolder, Path.GetFileName(this.ImgName)));
            }
            if (File.Exists(Path.Combine(importFolder, Path.GetFileName(this.DDTName))))
            {
                File.Delete(Path.Combine(importFolder, Path.GetFileName(this.DDTName)));
            }

            IOHelper.CopyFile(this.ImgName, Path.Combine(importFolder, Path.GetFileName(this.ImgName)));
            IOHelper.CopyFile(this.DDTName, Path.Combine(importFolder, Path.GetFileName(this.DDTName)));
            Logger.Print("开始对资源打补丁");
            List <string> pFileList = SearchPatchingFiles(table, patchFolder);

            Logger.Print(string.Format("有 {0} 个资源文件需要打补丁", pFileList.Count));


            FileStream imgStream = File.Open(Path.Combine(importFolder, Path.GetFileName(this.ImgName)),
                                             FileMode.Open, FileAccess.ReadWrite);
            FileStream ddtStream = File.Open(Path.Combine(importFolder, Path.GetFileName(this.DDTName)),
                                             FileMode.Open, FileAccess.ReadWrite);
            BinaryWriter imgWriter = new BinaryWriter(imgStream);
            BinaryWriter ddtWriter = new BinaryWriter(ddtStream);

            Entry   vEntry;
            SubFile vSubFile;

            for (int i = 0; i < pFileList.Count; i++)
            {
                if (fDictionary.ContainsKey(pFileList[i]))
                {
                    byte[] data = null;

                    vEntry   = fDictionary[pFileList[i]];
                    vSubFile = tempSubFileDictionary[pFileList[i]];
                    if (Path.GetExtension(vSubFile.FileName).ToLower().Equals(".lb") &&
                        vSubFile.SubItems.Count > 0)
                    {
                        //lb包有子文件,启动压缩
                        LB     lbContainer = new LB();
                        byte[] packedBytes = lbContainer.Repack(getBaseDir(vSubFile.FileName), vSubFile.FileName, srcFolder, patchFolder, vSubFile.SubItems);
                        //File.WriteAllBytes("temp/" + Path.GetFileName(vSubFile.FileName), packedBytes);
                        data = packedBytes;
                    }
                    else
                    {
                        string tmpPath = "";
                        if (File.Exists(patchFolder + "/" + vSubFile.FileName))
                        {
                            tmpPath = patchFolder + "/" + vSubFile.FileName;
                        }
                        else
                        {
                            tmpPath = srcFolder + "/" + vSubFile.FileName;
                        }

                        data = File.ReadAllBytes(tmpPath);
                    }

                    if (data != null)
                    {
                        var t_length   = data.Length;
                        var chunk_size = 0;
                        if ((t_length % 0x800) == 0)
                        {
                            chunk_size = t_length;
                        }
                        else
                        {
                            chunk_size = t_length + 0x800 - t_length % 0x800;
                        }

                        var o_chunk_sz = 0;
                        if ((vEntry.Size % 0x800) == 0)
                        {
                            o_chunk_sz = vEntry.Size;
                        }
                        else
                        {
                            o_chunk_sz = vEntry.Size + 0x800 - vEntry.Size % 0x800;
                        }

                        if (chunk_size > o_chunk_sz)
                        {
                            //追加补丁
                            imgWriter.Seek(0, SeekOrigin.End);
                            var offset = imgWriter.BaseStream.Position / 0x800;
                            Logger.Print(string.Format("Append res file{0} to offfset {1:x8}", vSubFile.FileName,
                                                       offset * 0x800, t_length));
                            imgWriter.Write(data);
                            imgWriter.AlignPosition(0x800);
                            ddtWriter.Seek(vEntry.Ptr, SeekOrigin.Begin);
                            ddtWriter.Seek(4, SeekOrigin.Current);
                            ddtWriter.Write((int)offset);
                            ddtWriter.Write((int)t_length);
                        }
                        else
                        {
                            //原位替换
                            imgWriter.Seek(vEntry.Offset, SeekOrigin.Begin);
                            imgWriter.Write(Enumerable.Repeat((byte)0, vEntry.Size).ToArray());
                            imgWriter.Seek(vEntry.Offset, SeekOrigin.Begin);
                            var offset = vEntry.Offset / 0x800;
                            Logger.Print(string.Format("overrite res file{0} to offfset {1:x8}", vSubFile.FileName,
                                                       offset * 0x800, t_length));
                            imgWriter.Write(data);
                            ddtWriter.Seek(vEntry.Ptr, SeekOrigin.Begin);
                            ddtWriter.Seek(4, SeekOrigin.Current);
                            ddtWriter.Write((int)offset);
                            ddtWriter.Write((int)t_length);
                        }
                    }
                }
            }
            imgWriter.Close();
            ddtWriter.Close();
            Logger.Print("补丁结束。Have Fun");
        }