public FieldInvoke GetOffsetWork() { return(new FieldInvoke( (Stream, FromReader, Struct) => { XBXHeader Header = Struct; uint Count = (Header.EntryLen * Header.EntriesCount); if (FromReader) { StructReader Reader = new StructReader(Stream); Header.Offsets = new uint[Count]; for (uint i = 0; i < Count; i++) { Header.Offsets[i] = Reader.ReadRawType(Const.UINT32); } Header.IsString = new bool[Header.EntryLen]; for (uint i = 0; i < Header.EntryLen; i++) { Header.IsString[i] = IsString(Stream, Header.Offsets[i] + Header.StrPos); } } else { for (uint i = 0, x = 0; i < Header.Offsets.Length; i++) { if (!Header.IsString[i % Header.EntryLen]) { continue; } Header.Offsets[i] = x; x += (uint)Encoding.GetByteCount(Header.Strings[i]) + 1; } StructWriter Writer = new StructWriter(Stream); for (uint i = 0; i < Count; i++) { Writer.WriteRawType(Const.UINT32, Header.Offsets[i]); } } return Header; })); }
public void Encode(Bitmap Texture, Stream Output, bool CloseStreams = true) { StructWriter Writer = new StructWriter(Output, (bool)IsBigEnddian); Writer.Write(0x2065727574786554); if (SteamVersion.Value) { Writer.Write(0x20202020); Writer.Write(0); //0xC, section length Writer.WriteRawType(Const.UINT64, SteamUnk); Writer.Write(0); //0x18, pnglen Writer.WriteRawType(Const.UINT16, (ushort)TexSize.Width); Writer.WriteRawType(Const.UINT16, (ushort)TexSize.Height); } else { Writer.Write(0); //0x8, blocklen Writer.WriteRawType(Const.UINT32, Flags); Writer.Write(0); //0x10, pnglen Writer.WriteRawType(Const.UINT32, (uint)TexSize.Width); Writer.WriteRawType(Const.UINT32, (uint)TexSize.Height); } if (Tiled) { Texture = Retile(Texture); } uint SectionLength; if (SteamVersion.Value) { byte[] Buffer = new byte[Texture.Width * Texture.Height * 4]; fixed(void *pBuff = &Buffer[0]) { int Stride = Texture.Width; uint *pPixel = (uint *)pBuff; unchecked { for (int i = 0; i < Buffer.Length / 4; i++) { int X = i % Stride; int Y = i / Stride; uint ARGB = (uint)Texture.GetPixel(X, Y).ToArgb(); //ARGB => ABGR *pPixel++ = (ARGB & 0xFF00FF00) | ((ARGB & 0x00FF0000) >> 8 * 2) | ((ARGB & 0x000000FF) << 8 * 2); } } } if (Compressed) { Buffer = LZSSCompress(Buffer); } Writer.Write(Buffer); SectionLength = (uint)Writer.BaseStream.Position; uint TexLen = SectionLength - 0x20; Writer.Seek(0xC, 0); Writer.WriteRawType(Const.UINT32, SectionLength); Writer.Seek(0x18, 0); Writer.WriteRawType(Const.UINT32, TexLen); } else { Texture.Save(Writer.BaseStream, ImageFormat.Png); SectionLength = (uint)Writer.BaseStream.Position; uint PngLen = SectionLength - 0x1C; Writer.Seek(0x8, 0); Writer.WriteRawType(Const.UINT32, SectionLength); Writer.Seek(0x10, 0); Writer.WriteRawType(Const.UINT32, PngLen); } Writer.Seek(SectionLength, 0); while (Writer.BaseStream.Position % (SteamVersion.Value ? 8 : 4) != 0) { Writer.Write((byte)0x0); } StructReader Reader = new StructReader(this.Texture, (bool)IsBigEnddian); Reader.Seek(SteamVersion.Value ? 0x0C : 0x08, 0); Reader.Seek(Reader.ReadRawType(Const.UINT32), 0); while (Reader.BaseStream.Position % (SteamVersion.Value ? 8 : 4) != 0) { Reader.ReadByte(); } Reader.BaseStream.CopyTo(Writer.BaseStream); Writer.Flush(); if (CloseStreams) { Writer.Close(); Output?.Close(); } }