public static string[] ReadZeroTerminatedStringArrays(LimitedReader partialReader, bool withOffsets, out Dictionary <int, string>?offsets) { List <string> textures = new(); offsets = withOffsets ? new() : null; var startOffset = partialReader.Offset; while (!partialReader.IsFinished()) { int start = partialReader.Offset; while (partialReader.ReadByte() != 0) { ; } int end = partialReader.Offset - 1; if (end == start && partialReader.IsFinished()) { break; } partialReader.Offset = start; var textureNameBytes = partialReader.ReadBytes(end - start); var textureName = System.Text.Encoding.ASCII.GetString(textureNameBytes); textures.Add(textureName); if (withOffsets) { offsets ![start - startOffset] = textureName;
public BLP(byte[] bytes, int start, int length) { var reader = new MemoryBinaryReader(bytes, start, length); Header = new BLPHeader(reader); uint w = Header.Width; uint h = Header.Height; Data = new Rgba32[Header.MipCount][]; int mipLevel; for (mipLevel = 0; mipLevel < Header.MipCount; ++mipLevel) { reader.Offset = (int)Header.GetMipOffset(mipLevel); var mipReader = new LimitedReader(reader, (int)Header.GetMipSize(mipLevel)); if (Header.ColorEncoding == ColorEncoding.Palette) { uint len = w * h; Data[mipLevel] = new Rgba32[w * h]; for (int j = 0; j < len; j++) { var b = mipReader.ReadByte(); var color = Header.PaletteBGRA ![b];
private WorldMapObjectPlacementData[] ReadWorldMapObjectPlacementData(LimitedReader reader, string[]?names) { Debug.Assert(names != null); int i = 0; WorldMapObjectPlacementData[] data = new WorldMapObjectPlacementData[reader.Size / 0x40]; while (!reader.IsFinished()) { data[i++] = new WorldMapObjectPlacementData(reader, names); } return(data); }
private M2PlacementData[] ReadM2PlacementData(LimitedReader reader, string[]?names) { Debug.Assert(names != null); int i = 0; M2PlacementData[] data = new M2PlacementData[reader.Size / 0x24]; while (!reader.IsFinished()) { data[i++] = new M2PlacementData(reader, names); } return(data); }
public ADT(IBinaryReader reader) { string[]? worldMapObjectsIds = null; string[]? m2Ids = null; Dictionary <int, string>?wmosNameOffsets = null; Dictionary <int, string>?m2NameOffsets = null; int chunkId = 0; while (!reader.IsFinished()) { var chunkName = reader.ReadChunkName(); var size = reader.ReadInt32(); var offset = reader.Offset; var partialReader = new LimitedReader(reader, size); if (chunkName == "MTEX") { Textures = ChunkedUtils.ReadZeroTerminatedStringArrays(partialReader, false, out _); } else if (chunkName == "MWMO") { ChunkedUtils.ReadZeroTerminatedStringArrays(partialReader, true, out wmosNameOffsets); } else if (chunkName == "MWID") { worldMapObjectsIds = ReadNameOffsets(partialReader, wmosNameOffsets); } else if (chunkName == "MODF") { WorldMapObjects = ReadWorldMapObjectPlacementData(partialReader, worldMapObjectsIds); } else if (chunkName == "MMDX") { ChunkedUtils.ReadZeroTerminatedStringArrays(partialReader, true, out m2NameOffsets); } else if (chunkName == "MMID") { m2Ids = ReadNameOffsets(partialReader, m2NameOffsets); } else if (chunkName == "MDDF") { M2Objects = ReadM2PlacementData(partialReader, m2Ids); } else if (chunkName == "MCNK") { Chunks[chunkId++] = new AdtChunk(partialReader); } reader.Offset = offset + size; } }
private string[] ReadNameOffsets(LimitedReader reader, Dictionary <int, string>?wmosNameOffsets) { Debug.Assert(wmosNameOffsets != null); int i = 0; string[] names = new string[reader.Size / 4]; while (!reader.IsFinished()) { names[i++] = wmosNameOffsets[reader.ReadInt32()]; } return(names); }
public T Deserialize <T>() where T : new() { var s_Resource = new T(); m_Stream.Skip(4); // Magic (BIN1) m_Stream.Skip(1); // Unknown (always 0?) Alignment = m_Stream.ReadUByte(); var s_SegmentCount = m_Stream.ReadUByte(); m_Stream.Skip(1); // Unknown (always 0?) var s_DataSize = m_Stream.ReadUInt32Flipped(); m_Stream.Skip(4); // Unknown (maybe alignment?) var s_Data = m_Stream.ReadBytes((int)s_DataSize); using var s_DataReader = new ZHMStream(new MemoryStream(s_Data)); for (var i = 0; i < s_SegmentCount; ++i) { var s_SegmentType = m_Stream.ReadUInt32(); var s_SegmentSize = m_Stream.ReadUInt32(); Console.WriteLine($"Found segment {i} with {s_SegmentSize} bytes of data. Type: {s_SegmentType:X08}."); if (SegmentParsers.TryGetValue(s_SegmentType, out var s_Parser)) { using var s_SegmentReader = new LimitedReader(m_Stream, s_SegmentSize, false); s_Parser.ParseSegment(s_SegmentReader, s_DataReader); } else { throw new Exception($"Could not find a segment parser for segment of type {s_SegmentType:X08}."); } } Console.WriteLine($"Read {s_SegmentCount} segments with {m_Stream.BaseStream.Length - m_Stream.BaseStream.Position} bytes left to read."); return(s_Resource); }
public WDT(IBinaryReader reader) { int chunkId = 0; Dictionary <int, string>?mwmosNameOffsets = null; while (!reader.IsFinished()) { var chunkName = reader.ReadChunkName(); var size = reader.ReadInt32(); var offset = reader.Offset; var partialReader = new LimitedReader(reader, size); if (chunkName == "MVER") { Version = reader.ReadUInt32(); } else if (chunkName == "MPHD") { Header = WDTHeader.Read(partialReader); } else if (chunkName == "MAIN") { Chunks[chunkId++] = new WDTChunk(partialReader); } else if (chunkName == "MWMO") { Mwmo = ChunkedUtils.ReadZeroTerminatedStringArrays(partialReader, true, out mwmosNameOffsets)[0]; } else if (chunkName == "MODF") { WorldMapObject = MODF.Read(partialReader); } reader.Offset = offset + size; } }