/// <exception cref="U2FException"/> /// <exception cref="System.IO.IOException"/> public static IU2FRequest ParseRequest(Stream inputStream) { using (var dataInputStream = new EndianReader(inputStream, Endianness.BigEndian)) { var version = dataInputStream.ReadByte(); if (version != Version) { throw new U2FException($"Unsupported message version: {version}"); } var command = dataInputStream.ReadByte(); switch (command) { case CommandRegister: { return RawMessageCodec.DecodeKeyRegisterRequest(ParseMessage(dataInputStream )); } case CommandAuthenticate: { return RawMessageCodec.DecodeKeySignRequest(ParseMessage (dataInputStream)); } default: { throw new U2FException($"Unsupported command: {command}"); } } } }
public static InitializationPacket ReadFrom(ArraySegment<byte> segment) { if (segment.Count < NoDataSize) { throw new InvalidPacketSizeException(segment, $"Data is too small, expected {NoDataSize} bytes but provided only {segment.Count}"); } var result = new InitializationPacket(); using (var stream = new MemoryStream(segment.Array, segment.Offset, segment.Count)) { var reader = new EndianReader(stream, Endianness.BigEndian); result.ChannelIdentifier = reader.ReadUInt32(); result.CommandIdentifier = reader.ReadByte(); CheckCommand(segment, result.CommandIdentifier); var payloadLengthHi = reader.ReadByte(); var payloadLengthLo = reader.ReadByte(); result.PayloadLength = (ushort)(payloadLengthHi << 8 | payloadLengthLo); } var remainingBytes = Math.Min(segment.Count - NoDataSize, result.PayloadLength); result.Data = new ArraySegment<byte>(segment.Array, segment.Offset + NoDataSize, remainingBytes); return result; }
private static void DumpSharedResources(string mapPath, EngineDatabase db) { ICacheFile cacheFile; ResourceTable resources; using (var reader = new EndianReader(File.OpenRead(mapPath), Endian.BigEndian)) { cacheFile = CacheFileLoader.LoadCacheFile(reader, db); resources = cacheFile.Resources.LoadResourceTable(reader); } using (var output = new StreamWriter(Path.ChangeExtension(mapPath, ".txt"))) { output.WriteLine("Shared resources referenced by {0}:", Path.GetFileName(mapPath)); output.WriteLine(); output.WriteLine("Rsrc Datum Map File Class Tag"); output.WriteLine("---------- -------- ----- ---"); foreach (Resource resource in resources.Resources.Where(r => r.Location != null && r.ParentTag != null)) { // If either page has a null file path, then it's shared ResourcePointer loc = resource.Location; string primaryFile = (loc.PrimaryPage != null) ? loc.PrimaryPage.FilePath : null; string secondaryFile = (loc.SecondaryPage != null) ? loc.SecondaryPage.FilePath : null; if (primaryFile != null || secondaryFile != null) { string className = CharConstant.ToString(resource.ParentTag.Class.Magic); string name = cacheFile.FileNames.GetTagName(resource.ParentTag) ?? resource.ParentTag.Index.ToString(); string fileName = primaryFile ?? secondaryFile; fileName = fileName.Substring(fileName.IndexOf('\\') + 1); output.WriteLine("{0} {1, -12} {2} {3}", resource.Index, fileName, className, name); } } } }
public List<LocalizedString> LoadStrings(IReader reader) { var result = new List<LocalizedString>(); if (StringCount == 0) return result; byte[] stringData = ReadLocaleData(reader); using (var stringReader = new EndianReader(new MemoryStream(stringData), Endian.BigEndian)) { reader.SeekTo(LocaleIndexTableLocation.AsOffset()); // Read each locale for (int i = 0; i < StringCount; i++) { // Read the offset and stringID StringID id; int offset; ReadLocalePointer(reader, out id, out offset); if (offset >= stringReader.Length) break; // Bad table - bail out so we don't end up in a huge memory-hogging loop stringReader.SeekTo(offset); string locale = stringReader.ReadUTF8(); result.Add(new LocalizedString(id, locale)); } } return result; }
/// <summary> /// Decrypts a segment of an EndianReader stream. /// </summary> /// <param name="Reader">The EndianReader to read from.</param> /// <param name="StartPosition">The stream position to decrypt from.</param> /// <param name="Length">The number of bytes to decrypt.</param> /// <param name="Key">The decryption key as a string.</param> /// <returns>A new EndianReader stream containing only the decrypted segment.</returns> public static EndianReader DecryptSegment(EndianReader Reader, int StartPosition, int Length, string Key) { Reader.SeekTo(StartPosition); if (Length % 16 != 0) Length += 16 - Length % 16; byte[] data = Reader.ReadBytes(Length); byte[] bKey = System.Text.Encoding.ASCII.GetBytes(Key); byte[] XOR = new byte[bKey.Length]; byte[] IV = new byte[bKey.Length]; for (int i = 0; i < bKey.Length; i++) { XOR[i] = (byte)(bKey[i] ^ 0xFFA5); IV[i] = (byte)(XOR[i] ^ 0x3C); } var aes = new AesManaged() { Mode = CipherMode.CBC, Key = XOR, IV = IV, Padding = PaddingMode.Zeros }; Stream stream = (Stream)new MemoryStream(aes.CreateDecryptor(aes.Key, aes.IV).TransformFinalBlock(data, 0, data.Length)); return new EndianReader(stream, EndianFormat.Big); }
private void makePatch_Click(object sender, EventArgs e) { Patch patch = new Patch(); patch.Name = patchName.Text; patch.Description = patchDescription.Text; patch.Author = patchAuthor.Text; IReader originalReader = new EndianReader(File.OpenRead(unmoddedPath.Text), Endian.BigEndian); IReader newReader = new EndianReader(File.OpenRead(moddedPath.Text), Endian.BigEndian); ThirdGenVersionInfo version = new ThirdGenVersionInfo(originalReader); BuildInfoLoader loader = new BuildInfoLoader(XDocument.Load(@"Formats\SupportedBuilds.xml"), @"Formats\"); BuildInformation buildInfo = loader.LoadBuild(version.BuildString); ThirdGenCacheFile originalFile = new ThirdGenCacheFile(originalReader, buildInfo, version.BuildString); ThirdGenCacheFile newFile = new ThirdGenCacheFile(newReader, buildInfo, version.BuildString); MetaComparer.CompareMeta(originalFile, originalReader, newFile, newReader, patch); LocaleComparer.CompareLocales(originalFile, originalReader, newFile, newReader, patch); originalReader.Close(); newReader.Close(); IWriter output = new EndianWriter(File.OpenWrite(outPath.Text), Endian.BigEndian); AssemblyPatchWriter.WritePatch(patch, output); output.Close(); MessageBox.Show("Done!"); }
/// <summary> /// Extracts a Wwise OGG and converts it to a "regular" OGG file. /// </summary> /// <param name="reader">The stream to read from.</param> /// <param name="offset">The offset of the data to extract.</param> /// <param name="size">The size of the data to extract.</param> /// <param name="outPath">The path of the file to save to.</param> public static void ExtractWwiseToOGG(EndianReader reader, int offset, int size, string outPath) { // Just extract the RIFX to a temporary file string tempFile = Path.GetTempFileName(); try { using (EndianWriter output = new EndianWriter(File.OpenWrite(tempFile), EndianFormat.BigEndian)) { reader.SeekTo(offset); StreamUtil.Copy(reader, output, size); } // Run ww2ogg to convert the resulting RIFX to an OGG RunProgramSilently("Helpers/ww2ogg.exe", string.Format("\"{0}\" -o \"{1}\" --pcb Helpers/packed_codebooks_aoTuV_603.bin", tempFile, outPath), Directory.GetCurrentDirectory()); // Run revorb to fix up the OGG RunProgramSilently("Helpers/revorb.exe", "\"" + outPath + "\"", Directory.GetCurrentDirectory()); } finally { // Delete the old RIFX file if (File.Exists(tempFile)) File.Delete(tempFile); } }
/// <summary> /// Processes the provided <paramref name="marker" /> in the stream held by /// <paramref name="reader" /> to determine the Endian setting of the stream. /// Advances the position in the stream by four bytes and returns a new /// binary reader to read the stream with the correct Endian setting. /// </summary> /// <returns> /// New BinaryReader for the stream. /// </returns> public static BinaryReader ProcessEndianMarker(this BinaryReader reader, uint marker) { var streamMarker = reader.ReadUInt32(); if (streamMarker == marker) { return reader; } var swappedStreamMarker = (streamMarker << 24) | ((streamMarker & 0x0000FF00) << 8) | ((streamMarker & 0x00FF0000) >> 8) | (streamMarker >> 24); if (swappedStreamMarker != marker) { throw new IOException($"Endian stream marker mismatch: received 0x{streamMarker.ToString("x8")}, expected 0x{marker.ToString("x8")}."); } var result = new EndianReader(reader); var source = reader as EndianReader; result.Endian = source != null ? source.Endian.Switch : Endian.NonNative; return result; }
/// <summary> /// Extracts the raw contents of a sound to a file. /// </summary> /// <param name="reader">The stream to read from.</param> /// <param name="offset">The offset of the data to extract.</param> /// <param name="size">The size of the data to extract.</param> /// <param name="outPath">The path of the file to save to.</param> public static void ExtractRaw(EndianReader reader, int offset, int size, string outPath) { using (EndianWriter output = new EndianWriter(File.OpenWrite(outPath), EndianFormat.BigEndian)) { // Just copy the data over to the output stream reader.SeekTo(offset); StreamUtil.Copy(reader, output, size); } }
/// <summary> /// Initializes a new instance of the <see cref="EndianStream"/> class. /// </summary> /// <param name="stream">The stream to read from and write to.</param> /// <param name="endianness">The initial endianness to use when operating on the stream.</param> /// <exception cref="System.ArgumentException">Thrown if <paramref name="stream"/> is not both readable and writable.</exception> public EndianStream(Stream stream, Endian endianness) { if (!stream.CanRead || !stream.CanWrite) throw new ArgumentException("The input stream must be both readable and writable."); _stream = stream; _reader = new EndianReader(stream, endianness); _writer = new EndianWriter(stream, endianness); }
public static void Copy(EndianReader input, EndianWriter output) { const int BufferSize = 0x1000; var buffer = new byte[BufferSize]; int read; while ((read = input.ReadBlock(buffer, 0, BufferSize)) > 0) output.WriteBlock(buffer, 0, read); }
/// <summary> /// Constructs a new EndianStream based off of a Stream object. /// </summary> /// <param name="stream">The Stream to use. It must at least be available for reading or writing.</param> /// <param name="endianness">The endianness to use when performing I/O operations.</param> public EndianStream(Stream stream, Endian endianness) { _stream = stream; if (stream.CanRead) _reader = new EndianReader(stream, endianness); if (stream.CanWrite) _writer = new EndianWriter(stream, endianness); if (_reader == null && _writer == null) throw new ArgumentException("The input stream cannot be read from or written to."); }
public void Load(string filePath) { // Open Film FilmPath = filePath; var stream = new EndianReader(new FileStream(FilmPath, FileMode.Open), Endian.BigEndian); ValidateFilm(stream); LoadPlayerTable(stream); stream.Close(); }
public H2VistaMapPointerReader(ProcessMemoryStream stream) { // Get the base address of the process's main module // All addresses have to be based off of this because the game // randomizes its address space _baseAddress = (long) stream.BaseProcess.MainModule.BaseAddress; var reader = new EndianReader(stream, BitConverter.IsLittleEndian ? Endian.LittleEndian : Endian.BigEndian); FindMapHeader(reader); ReadMapPointers(reader); ReadMapHeader(reader); ProcessMapHeader(); }
public static CacheFile GetCache(string Filename) { CacheFile retCache = null; using (var fs = new FileStream(Filename, FileMode.Open, FileAccess.Read)) { var Reader = new EndianReader((Stream)fs, EndianFormat.Big); var head = Reader.ReadInt32(); if (head == 1684104552) Reader.Format = EndianFormat.Little; var v = Reader.ReadInt32(); switch (v) { case 5: //H1X case 7: //HPC case 609: //HCE Reader.SeekTo(64); break; case 8: //H2? Reader.SeekTo(36); switch (Reader.ReadInt32()) { case 0: //H2X Reader.SeekTo(288); break; case -1: //H2V Reader.SeekTo(300); break; } break; default: //360 Reader.SeekTo(284); break; } var build = Reader.ReadString(32); var node = CacheFile.GetBuildNode(build); switch (node.Attributes["definitions"].Value) { case "Halo3": retCache = new Halo3.CacheFile(Filename, build); break; case "HaloODST": retCache = new HaloODST.CacheFile(Filename, build); break; } } if (retCache != null) { retCache.LoadPlayZone(); return retCache; } else throw new NotSupportedException("Cache version is unknown, unsupported or invalid."); }
/// <summary> /// Extracts an xWMA sound and converts it to another format. /// </summary> /// <param name="reader">The stream to read from.</param> /// <param name="offset">The offset of the data to extract.</param> /// <param name="rifx">The RIFX data for the sound.</param> /// <param name="outPath">The path of the file to save to. The file extension will determine the output format.</param> public static void ExtractAndConvertXWMA(EndianReader reader, int offset, RIFX rifx, string outPath) { // Extract a WAV to a temporary file and then convert it string tempPath = Path.GetTempFileName(); try { ExtractXWMAToWAV(reader, offset, rifx, tempPath); ConvertFile(tempPath, outPath); } finally { // Delete the temporary file if (File.Exists(tempPath)) File.Delete(tempPath); } }
public void BinaryWriterCompatible_NativeEndian() { var stream = new MemoryStream(); var writer = new BinaryWriter(stream); var reader = new EndianReader(stream); foreach (TestValue value in _testValuesWithBits) { value.Write(writer); } writer.Flush(); stream.Position = 0; foreach (TestValue value in _testValuesWithBits) { value.Read(reader); } }
public EndianIO(string fileName, EndianType endiantype, bool Open, bool IsNewFile) { EndianType = endiantype; FileName = fileName; var mode = IsNewFile ? FileMode.Create : FileMode.Open; try { Stream = new FileStream(FileName, mode); Reader = new EndianReader(Stream, EndianType); Writer = new EndianWriter(Stream, EndianType); if (!Open) { Close(); } } catch { } }
public BitmapData(EndianReader Reader, int Address) { Reader.SeekTo(Address); Class = Reader.ReadString(4); Width = Reader.ReadUInt16(); Height = Reader.ReadUInt16(); Depth = Reader.ReadUInt16(); //Flags = new Bitmask(Reader.ReadByte()); Type = (BitmapType)Reader.ReadUInt16(); Format = (BitmapFormat)Reader.ReadUInt16(); Flags = new Bitmask(Reader.ReadUInt16()); RegX = Reader.ReadUInt16(); RegY = Reader.ReadUInt16(); MipmapCount = Reader.ReadInt32(); PixelsOffset = Reader.ReadInt32(); PixelsSize = Reader.ReadInt32(); Reader.SeekTo(Address + 48); }
private void button1_Click(object sender, EventArgs e) { OpenFileDialog ofd = new OpenFileDialog(); if (ofd.ShowDialog() == DialogResult.OK) { FileStream stream = new FileStream(ofd.FileName, FileMode.Open); EndianReader reader = new EndianReader(stream, EndianType.BigEndian); EndianWriter writer = new EndianWriter(stream, EndianType.BigEndian); int CSum = 0; reader.BaseStream.Position = 0xD000; for (int i = 0; i < 0x768; i += 4) CSum += reader.ReadInt32(); writer.Write(CSum); writer.Flush(); writer.Close(); reader.Close(); MessageBox.Show("New Checksum: " + CSum.ToString("X2"), "Done!"); } }
public bitmap(CacheBase Cache, int Address) { int magic = Cache.Magic; EndianReader Reader; if (Address < 0) //external bitmap { var fs = new FileStream(Cache.FilePath + "\\bitmaps.map", FileMode.Open, FileAccess.Read); Reader = new EndianReader(fs, EndianFormat.LittleEndian); Reader.SeekTo(8); var indexOffset = Reader.ReadInt32(); var index = Address + Cache.Magic; Reader.SeekTo(indexOffset + 12 * index + 8); Address = Reader.ReadInt32(); magic = -Address; } else Reader = Cache.Reader; #region BitmapData Chunk Reader.SeekTo(Address + 96); int iCount = Reader.ReadInt32(); int iOffset = Reader.ReadInt32() - magic; for (int i = 0; i < iCount; i++) Bitmaps.Add(new BitmapData(Reader, iOffset + 48 * i)); #endregion if (Reader != Cache.Reader) { Reader.Close(); Reader.Dispose(); //add flag so the GetRawFromID function //can tell that it's an external bitmap foreach (var bData in Bitmaps) bData.PixelsOffset |= int.MinValue; //0x80000000 } }
public static ContinuationPacket ReadFrom(ArraySegment<byte> segment, int maxDataSize) { if (segment.Count < NoDataSize) { throw new InvalidPacketSizeException(segment, $"Data is too small, expected {NoDataSize} bytes but provided only {segment.Count}"); } var result = new ContinuationPacket(); using (var stream = new MemoryStream(segment.Array, segment.Offset, segment.Count)) { var reader = new EndianReader(stream, Endianness.BigEndian); result.ChannelIdentifier = reader.ReadUInt32(); result.PaketSequence = reader.ReadByte(); CheckSequence(segment, result.PaketSequence); } var remainingBytes = Math.Min(maxDataSize, segment.Count - NoDataSize); result.Data = new ArraySegment<byte>(segment.Array, segment.Offset + NoDataSize, remainingBytes); return result; }
public SoundPathRandomRange(EndianReader reader) { HorizontalRange = reader.ReadSingle(); VerticalRange = reader.ReadSingle(); }
public LocaleTable(CacheBase Cache, Language Lang) { cache = Cache; EndianReader Reader = cache.Reader; CacheHeader CH = cache.Header; #region Get Info int matgOffset = -1; foreach (IndexItem item in cache.IndexItems) { if (item.ClassCode == "matg") { matgOffset = item.Offset; break; } } if (matgOffset == -1) { return; } int localeStart = int.Parse(cache.buildNode.Attributes["localesStart"].Value); Reader.SeekTo(matgOffset + localeStart + (int)Lang * int.Parse(cache.buildNode.Attributes["languageSize"].Value)); int localeCount = Reader.ReadInt32(); int tableSize = Reader.ReadInt32(); int indexOffset = Reader.ReadInt32() + CH.localeModifier; int tableOffset = Reader.ReadInt32() + CH.localeModifier; #endregion #region Read Indices Reader.SeekTo(indexOffset); int[] indices = new int[localeCount]; for (int i = 0; i < localeCount; i++) { this.Add(""); Reader.ReadInt32(); indices[i] = Reader.ReadInt32(); } #endregion #region Read Names Reader.SeekTo(tableOffset); EndianReader newReader = (cache.localesKey == "" || cache.localesKey == null) ? new EndianReader(new MemoryStream(Reader.ReadBytes(tableSize)), EndianFormat.BigEndian) : AES.DecryptSegment(Reader, tableOffset, tableSize, cache.localesKey); for (int i = 0; i < indices.Length; i++) { if (indices[i] == -1) { this[i] = "<null>"; continue; } newReader.SeekTo(indices[i]); int length; if (i == indices.Length - 1) { length = tableSize - indices[i]; } else { length = (indices[i + 1] != -1) ? indices[i + 1] - indices[i] : indices[i + 2] - indices[i]; } if (length == 1) { this[i] = "<blank>"; continue; } this[i] = newReader.ReadString(length); } newReader.Close(); newReader.Dispose(); #endregion }
private ScenarioStructureBsp ConvertScenarioStructureBsp(ScenarioStructureBsp sbsp, CachedTagInstance instance, Dictionary <ResourceLocation, Stream> resourceStreams) { sbsp.CollisionBspResource = ConvertStructureBspTagResources(sbsp, resourceStreams); sbsp.PathfindingResource = ConvertStructureBspCacheFileTagResources(sbsp, resourceStreams); sbsp.Unknown86 = 1; // // Set compatibility flag for H3 mopps // if (BlamCache.Version == CacheVersion.Halo3Retail) { sbsp.CompatibilityFlags = ScenarioStructureBsp.StructureBspCompatibilityValue.UseMoppIndexPatch; } else { sbsp.CompatibilityFlags = ScenarioStructureBsp.StructureBspCompatibilityValue.None; } // // Fix cluster tag ref and decorator grids // var resource = sbsp.Geometry.Resource; if (resource != null && resource.Page.Index >= 0 && resource.GetLocation(out var location)) { var resourceContext = new ResourceSerializationContext(CacheContext, sbsp.Geometry.Resource); var definition = CacheContext.Deserializer.Deserialize <RenderGeometryApiResourceDefinition>(resourceContext); using (var edResourceStream = new MemoryStream()) using (var edResourceReader = new EndianReader(edResourceStream, EndianFormat.LittleEndian)) { var pageable = sbsp.Geometry.Resource; if (pageable == null) { throw new ArgumentNullException("sbsp.Geometry.Resource"); } if (!edResourceStream.CanWrite) { throw new ArgumentException("The output stream is not open for writing", "outStream"); } pageable.GetLocation(out var resourceLocation); var cache = CacheContext.GetResourceCache(resourceLocation); if (!resourceStreams.ContainsKey(resourceLocation)) { resourceStreams[resourceLocation] = FlagIsSet(PortingFlags.Memory) ? new MemoryStream() : (Stream)CacheContext.OpenResourceCacheReadWrite(resourceLocation); if (FlagIsSet(PortingFlags.Memory)) { using (var resourceStream = CacheContext.OpenResourceCacheRead(resourceLocation)) resourceStream.CopyTo(resourceStreams[resourceLocation]); } } cache.Decompress(resourceStreams[resourceLocation], pageable.Page.Index, pageable.Page.CompressedBlockSize, edResourceStream); var inVertexStream = VertexStreamFactory.Create(CacheVersion.HaloOnline106708, edResourceStream); foreach (var cluster in sbsp.Clusters) { List <ScenarioStructureBsp.Cluster.DecoratorGrid> newDecoratorGrids = new List <ScenarioStructureBsp.Cluster.DecoratorGrid>(); foreach (var grid in cluster.DecoratorGrids) { grid.DecoratorGeometryIndex_HO = grid.DecoratorGeometryIndex_H3; grid.DecoratorIndex_HO = grid.DecoratorIndex_H3; if (grid.Amount == 0) { newDecoratorGrids.Add(grid); } else { List <TinyPositionVertex> vertices = new List <TinyPositionVertex>(); // Get the buffer the right grid var vertexBuffer = definition.VertexBuffers[grid.DecoratorGeometryIndex_HO].Definition; // Get the offset from the grid edResourceStream.Position = vertexBuffer.Data.Address.Offset + grid.DecoratorGeometryOffset; // Read all vertices and add to the list for (int i = 0; i < grid.Amount; i++) { vertices.Add(inVertexStream.ReadTinyPositionVertex()); } // Get the new grids List <ScenarioStructureBsp.Cluster.DecoratorGrid> newGrids = ConvertDecoratorGrid(vertices, grid); // Add all to list foreach (var newGrid in newGrids) { newDecoratorGrids.Add(newGrid); } } } cluster.DecoratorGrids = newDecoratorGrids; } } } // // Temporary Fixes: // // Without this 005_intro crash on cortana sbsp sbsp.Geometry2.UnknownSections = new List <RenderGeometry.UnknownSection>(); return(sbsp); }
public void ReadHash(EndianReader reader) { Index = reader.ReadUInt64(); reader.Read(Hash, 0, 0x14); HashZero = reader.ReadUInt32(); }
/// <summary> /// Reads a DatumIndex from a EndianReader and returns it. /// </summary> /// <param name="reader">The EndianReader to read from.</param> /// <returns>The DatumIndex that was read.</returns> public static DatumIndex ReadFrom(EndianReader reader) { return(new DatumIndex(reader.ReadUInt32())); }
public scenario_structure_bsp(CacheBase Cache, int Address) { cache = Cache; EndianReader Reader = Cache.Reader; Reader.SeekTo(Address); #region sldt ID //sldt's sections address will be used instead of the one in sbsp int sectionAddress = 0; foreach (var item in Cache.IndexItems) { if (item.ClassCode == "scnr") { Reader.SeekTo(item.Offset + 12); int cnt = Reader.ReadInt32(); int ptr = Reader.ReadInt32() - Cache.Magic; int bspIndex = 0; for (int i = 0; i < cnt; i++) { Reader.SeekTo(ptr + 104 * i + 12); if (Cache.IndexItems.GetItemByID(Reader.ReadInt32()).Offset == Address) { bspIndex = i; break; } } Reader.SeekTo(item.Offset + 1720 + 12); int sldtID = Reader.ReadInt32(); int sldtAddress = Cache.IndexItems.GetItemByID(sldtID).Offset; Reader.SeekTo(sldtAddress + 4); cnt = Reader.ReadInt32(); ptr = Reader.ReadInt32() - Cache.Magic; for (int i = 0; i < cnt; i++) { Reader.SeekTo(ptr + 436 * i + 2); if (Reader.ReadInt16() != bspIndex) continue; Reader.SeekTo(ptr + 436 * i + 312); sectionAddress = Reader.ReadInt32() - Cache.Magic; Reader.SeekTo(ptr + 436 * i + 428); geomRawID = Reader.ReadInt32(); } break; } } #endregion Reader.SeekTo(Address + 60); XBounds = new RealBounds(Reader.ReadSingle(), Reader.ReadSingle()); YBounds = new RealBounds(Reader.ReadSingle(), Reader.ReadSingle()); ZBounds = new RealBounds(Reader.ReadSingle(), Reader.ReadSingle()); #region Clusters Block Reader.SeekTo(Address + 180); int iCount = Reader.ReadInt32(); int iOffset = Reader.ReadInt32() - Cache.Magic; for (int i = 0; i < iCount; i++) Clusters.Add(new Cluster(Cache, iOffset + 236 * i)); #endregion #region Shaders Block Reader.SeekTo(Address + 192); iCount = Reader.ReadInt32(); iOffset = Reader.ReadInt32() - Cache.Magic; for (int i = 0; i < iCount; i++) Shaders.Add(new Halo3Beta.render_model.Shader(Cache, iOffset + 36 * i)); #endregion #region GeometryInstances Block Reader.SeekTo(Address + 432); iCount = Reader.ReadInt32(); iOffset = Reader.ReadInt32() - Cache.Magic; for (int i = 0; i < iCount; i++) GeomInstances.Add(new InstancedGeometry(Cache, iOffset + 120 * i)); #endregion Reader.SeekTo(Address + 580); RawID1 = Reader.ReadInt32(); #region ModelSections Block Reader.SeekTo(Address + 740); iCount = Reader.ReadInt32(); iOffset = Reader.ReadInt32() - Cache.Magic; for (int i = 0; i < iCount; i++) ModelSections.Add(new Halo3Beta.render_model.ModelSection(Cache, sectionAddress + 76 * i)); #endregion #region BoundingBox Block Reader.SeekTo(Address + 752); iCount = Reader.ReadInt32(); iOffset = Reader.ReadInt32() - Cache.Magic; for (int i = 0; i < iCount; i++) BoundingBoxes.Add(new Halo3Beta.render_model.BoundingBox(Cache, iOffset + 44 * i)); #endregion Reader.SeekTo(Address + 860); RawID2 = Reader.ReadInt32(); Reader.SeekTo(Address + 892); RawID3 = Reader.ReadInt32(); }
public IndexTable(CacheBase Cache) { cache = Cache; var IH = cache.IndexHeader; var CH = cache.Header; var Reader = cache.Reader; ClassList = new List <TagClass>(); #region Read Class List Reader.SeekTo(IH.tagClassIndexOffset); for (int i = 0; i < IH.tagClassCount; i++) { TagClass tc = new TagClass(); tc.ClassCode = Reader.ReadString(4); tc.Parent = Reader.ReadString(4); tc.Parent2 = Reader.ReadString(4); tc.StringID = Reader.ReadInt32(); ClassList.Add(tc); } #endregion #region Read Tags' Info Reader.SeekTo(IH.tagInfoOffset); for (int i = 0; i < IH.tagCount; i++) { IndexItem item = new IndexItem() { Cache = cache }; item.ClassIndex = Reader.ReadInt16(); item.ID = (Reader.ReadInt16() << 16) | i; item.Offset = Reader.ReadInt32() - cache.Magic; item.metaIndex = i; this.Add(item); } #endregion #region Read Indices Reader.SeekTo(CH.fileTableIndexOffset); int[] indices = new int[IH.tagCount]; for (int i = 0; i < IH.tagCount; i++) { indices[i] = Reader.ReadInt32(); } #endregion #region Read Names Reader.SeekTo(CH.fileTableOffset); EndianReader newReader = (cache.tagsKey == "" || cache.tagsKey == null) ? new EndianReader(new MemoryStream(Reader.ReadBytes(CH.fileTableSize)), EndianFormat.BigEndian) : AES.DecryptSegment(Reader, CH.fileTableOffset, CH.fileTableSize, cache.tagsKey); for (int i = 0; i < indices.Length; i++) { if (indices[i] == -1) { this[i].Filename = "<null>"; continue; } newReader.SeekTo(indices[i]); int length; if (i == indices.Length - 1) { length = CH.fileTableSize - indices[i]; } else { if (indices[i + 1] == -1) { int index = -1; for (int j = i + 1; j < indices.Length; j++) { if (indices[j] != -1) { index = j; break; } } length = (index == -1) ? CH.fileTableSize - indices[i] : indices[index] - indices[i]; } else { length = indices[i + 1] - indices[i]; } } if (length == 1) { this[i].Filename = "<blank>"; continue; } if (length < 0) { int i0 = indices[i]; int i1 = indices[i + 1]; int i2 = indices[i + 2]; int i3 = indices[i + 3]; } this[i].Filename = newReader.ReadString(length); } newReader.Close(); newReader.Dispose(); #endregion }
public void GetRmt2Info(Stream cacheStream) { if (Rmt2TagsInfo.Count != 0) { return; } if (!cacheStream.CanRead) { Console.Write("Waiting for cache stream to become available..."); while (!cacheStream.CanRead) { ; } Console.Write("done."); } using (var reader = new EndianReader(cacheStream, true)) { foreach (var instance in CacheContext.TagCache.TagTable) { if (instance == null || !instance.IsInGroup("rmt2") || instance.Name == null || instance.Name.StartsWith("s3d")) { continue; } if (!UseMS30 && instance.Name.StartsWith("ms30")) { continue; } var bitmaps = new List <string>(); var arguments = new List <string>(); var hoInstance = (CachedTagHaloOnline)instance; reader.SeekTo(hoInstance.HeaderOffset + hoInstance.DefinitionOffset + 0x48); var vectorArgsCount = reader.ReadInt32(); var vectorArgsAddress = reader.ReadUInt32(); if (vectorArgsCount != 0 && vectorArgsAddress != 0) { for (var i = 0; i < vectorArgsCount; i++) { reader.SeekTo(hoInstance.HeaderOffset + (vectorArgsAddress - 0x40000000) + (i * 0x4)); arguments.Add(CacheContext.StringTable.GetString(reader.ReadStringId())); } } reader.SeekTo(hoInstance.HeaderOffset + hoInstance.DefinitionOffset + 0x6C); var samplerArgsCount = reader.ReadInt32(); var samplerArgsAddress = reader.ReadUInt32(); if (samplerArgsCount != 0 && samplerArgsAddress != 0) { for (var i = 0; i < samplerArgsCount; i++) { reader.SeekTo(hoInstance.HeaderOffset + (samplerArgsAddress - 0x40000000) + (i * 0x4)); bitmaps.Add(CacheContext.StringTable.GetString(reader.ReadStringId())); } } Rmt2TagsInfo.Add(instance.Index, new List <List <string> > { bitmaps, arguments }); } } }
public override byte[] GetSoundRaw(int ID, int size) { var Entry = zone.RawEntries[ID & ushort.MaxValue]; if (Entry.SegmentIndex == -1) throw new InvalidDataException("Raw data not found."); var segment = play.Segments[Entry.SegmentIndex]; var sRaw = play.SoundRawChunks[segment.SoundRawIndex]; var reqPage = play.Pages[segment.RequiredPageIndex]; var optPage = play.Pages[segment.OptionalPageIndex]; if (size == 0) size = (reqPage.CompressedSize != 0) ? reqPage.CompressedSize : optPage.CompressedSize; var reqSize = size - sRaw.RawSize; var optSize = size - reqSize; //if (reqPage.CompressedSize != reqPage.DecompressedSize || optPage.CompressedSize != optPage.DecompressedSize) // throw new Exception("COMPRESSED DATA"); //if (sRaw.Sizes.Count > 1) // throw new Exception("MULTIPLE SEGMENTS"); byte[] buffer; byte[] data = new byte[size]; int offset; EndianReader er; string fName = ""; #region REQUIRED if (reqSize > 0) { if (reqPage.CacheIndex != -1) { fName = play.SharedCaches[reqPage.CacheIndex].FileName; fName = fName.Substring(fName.LastIndexOf('\\')); fName = FilePath + fName; if (fName == Filename) er = Reader; else er = new EndianReader(new FileStream(fName, FileMode.Open, FileAccess.Read), EndianFormat.BigEndian); } else er = Reader; er.SeekTo(1136); offset = reqPage.RawOffset + er.ReadInt32(); er.SeekTo(offset); buffer = er.ReadBytes(reqPage.CompressedSize); Array.Copy(buffer, segment.RequiredPageOffset, data, 0, reqSize); if (er != Reader) { er.Close(); er.Dispose(); } } #endregion #region OPTIONAL if (segment.OptionalPageIndex != -1 && optSize > 0) { if (optPage.CacheIndex != -1) { fName = play.SharedCaches[optPage.CacheIndex].FileName; fName = fName.Substring(fName.LastIndexOf('\\')); fName = FilePath + fName; if (fName == Filename) er = Reader; else er = new EndianReader(new FileStream(fName, FileMode.Open, FileAccess.Read), EndianFormat.BigEndian); } else er = Reader; er.SeekTo(1136); offset = optPage.RawOffset + er.ReadInt32(); er.SeekTo(offset); buffer = er.ReadBytes(optPage.CompressedSize); if (buffer.Length > data.Length) data = buffer; else Array.Copy(buffer, segment.OptionalPageOffset, data, reqSize, optSize); if (er != Reader) { er.Close(); er.Dispose(); } } #endregion return data; }
static void Main(string[] args) { OpenFileDialog ofd = new OpenFileDialog(); ofd.Title = "Open Cache File"; ofd.Filter = "Blam Cache Files|*.map"; if (ofd.ShowDialog() != DialogResult.OK) return; SaveFileDialog sfd = new SaveFileDialog(); sfd.Title = "Save String Dump"; sfd.Filter = "Text Files|*.txt"; if (sfd.ShowDialog() != DialogResult.OK) return; string mapPath = ofd.FileName; string dumpPath = sfd.FileName; BuildInfoLoader loader = new BuildInfoLoader(@"Formats\SupportedBuilds.xml", "Formats"); ICacheFile cacheFile; LocaleTable locales; using (IReader reader = new EndianReader(File.OpenRead(mapPath), Endian.BigEndian)) { Console.WriteLine("Loading cache file..."); cacheFile = CacheFileLoader.LoadCacheFile(reader, loader); Console.WriteLine("Loading locales..."); locales = cacheFile.Languages[LocaleLanguage.English].LoadStrings(reader); } StreamWriter output = new StreamWriter(dumpPath); output.WriteLine("Input file: {0}.map", cacheFile.InternalName); output.WriteLine(); // Sort locales by stringID List<Locale> localesById = new List<Locale>(); foreach (Locale str in locales.Strings) { if (str != null) localesById.Add(str); } localesById.Sort((x, y) => x.ID.Value.CompareTo(y.ID.Value)); // Dump locales Console.WriteLine("Dumping locales..."); output.WriteLine("---------------"); output.WriteLine("English Locales"); output.WriteLine("---------------"); foreach (Locale str in localesById) { if (str != null) output.WriteLine("{0} = \"{1}\"", str.ID, str.Value); } output.WriteLine(); // Dump stringIDs Console.WriteLine("Dumping stringIDs..."); output.WriteLine("---------"); output.WriteLine("StringIDs"); output.WriteLine("---------"); int index = 0; foreach (string str in cacheFile.StringIDs) { if (str != null) output.WriteLine("0x{0:X} = \"{1}\"", index, str); else output.WriteLine("0x{0:X} = (null)", index); index++; } output.Close(); Console.WriteLine("Done!"); }
private List <ShaderTemplateItem> CollectRmt2Info(Stream cacheStream, CachedTag bmRmt2Instance, List <string> bmMaps, List <string> bmArgs) { var edRmt2BestStats = new List <ShaderTemplateItem>(); RenderMethodTemplate bmRmt2; PixelShader bmPixl; using (var blamStream = BlamCache.OpenCacheRead()) { bmRmt2 = BlamCache.Deserialize <RenderMethodTemplate>(blamStream, bmRmt2Instance); bmPixl = BlamCache.Deserialize <PixelShader>(blamStream, bmRmt2.PixelShader); } // loop trough all rmt2 and find the closest foreach (var edRmt2_ in Rmt2TagsInfo) { var rmt2Type = bmRmt2Instance.Name.Split("\\".ToArray())[1]; var edRmt2Tag = (CachedTagHaloOnline)CacheContext.TagCache.GetTag(edRmt2_.Key); // Ignore all rmt2 that are not of the same type. if (edRmt2Tag == null || !(edRmt2Tag.Name?.Contains(rmt2Type) ?? false)) { continue; } using (var reader = new EndianReader(cacheStream, true)) { reader.SeekTo(edRmt2Tag.HeaderOffset + edRmt2Tag.DefinitionOffset + 28); var edPixl = (CachedTagHaloOnline)CacheContext.TagCache.GetTag(reader.ReadInt32()); if (edPixl == null) { continue; } reader.SeekTo(edPixl.HeaderOffset + edPixl.DefinitionOffset + 0x4); var drawModeCount = reader.ReadInt32(); reader.SeekTo(edPixl.HeaderOffset + edPixl.DefinitionOffset + 0x14); var shaderCount = reader.ReadInt32(); if (bmPixl.DrawModes.Count > drawModeCount || bmPixl.Shaders.Count > shaderCount) { continue; } } int mapsCommon = 0; int argsCommon = 0; int mapsUncommon = 0; int argsUncommon = 0; int mapsMissing = 0; int argsMissing = 0; var edMaps_ = new List <string>(); var edArgs_ = new List <string>(); foreach (var a in edRmt2_.Value[0]) { edMaps_.Add(a); } foreach (var a in edRmt2_.Value[1]) { edArgs_.Add(a); } foreach (var a in bmMaps) { if (edMaps_.Contains(a)) { mapsCommon++; } } foreach (var a in bmMaps) { if (!edMaps_.Contains(a)) { mapsMissing++; } } foreach (var a in edMaps_) { if (!bmMaps.Contains(a)) { mapsUncommon++; } } foreach (var a in bmArgs) { if (edArgs_.Contains(a)) { argsCommon++; } } foreach (var a in bmArgs) { if (!edArgs_.Contains(a)) { argsMissing++; } } foreach (var a in edArgs_) { if (!bmArgs.Contains(a)) { argsUncommon++; } } edRmt2BestStats.Add(new ShaderTemplateItem { rmt2TagIndex = edRmt2_.Key, rmdfValuesMatchingCount = 0, mapsCountEd = edRmt2_.Value[0].Count, argsCountEd = edRmt2_.Value[1].Count, mapsCountBm = bmMaps.Count, argsCountBm = bmArgs.Count, mapsCommon = mapsCommon, argsCommon = argsCommon, mapsUncommon = mapsUncommon, argsUncommon = argsUncommon, mapsMissing = mapsMissing, argsMissing = argsMissing }); } return(edRmt2BestStats); }
public void TestFunctionParsing() { // This method is essentially test of the BytecodeEditor parser with the actual ui logic all removed GlobalTest.Init(); // Loads compressed packages, save them uncompressed. Load package, save re-compressed, compare results var packagesPath = GlobalTest.GetTestPackagesDirectory(); //var packages = Directory.GetFiles(packagesPath, "*.*", SearchOption.AllDirectories); var packages = Directory.GetFiles(packagesPath, "*.*", SearchOption.AllDirectories); foreach (var p in packages) { if (p.RepresentsPackageFilePath()) { (var game, var platform) = GlobalTest.GetExpectedTypes(p); // Use to skip //if (platform != MEPackage.GamePlatform.Xenon) continue; //if (game != MEGame.ME1) continue; Console.WriteLine($"Opening package {p}"); // Do not use package caching in tests var originalLoadedPackage = MEPackageHandler.OpenMEPackage(p, forceLoadFromDisk: true); foreach (var export in originalLoadedPackage.Exports.Where(x => x.ClassName == "Function" || x.ClassName == "State")) { //Console.WriteLine($" >> Decompiling {export.InstancedFullPath}"); var data = export.Data; var funcBin = ObjectBinary.From <UFunction>(export); //parse it out if (export.FileRef.Game == MEGame.ME3 || export.FileRef.Platform == MEPackage.GamePlatform.PS3) { var func = new Function(data, export); func.ParseFunction(); func.GetSignature(); if (export.ClassName == "Function") { var nativeBackOffset = export.FileRef.Game < MEGame.ME3 ? 7 : 6; var pos = data.Length - nativeBackOffset; string flagStr = func.GetFlags(); var nativeIndex = EndianReader.ToInt16(data, pos, export.FileRef.Endian); pos += 2; var flags = EndianReader.ToInt16(data, pos, export.FileRef.Endian); } else { //State //parse remaining var footerstartpos = 0x20 + funcBin.ScriptStorageSize; var footerdata = data.Slice(footerstartpos, (int)data.Length - (footerstartpos)); var fpos = 0; //ScriptFooterBlocks.Add(new ScriptHeaderItem("Probemask?", "??", fpos + footerstartpos) { length = 8 }); fpos += 0x8; //ScriptFooterBlocks.Add(new ScriptHeaderItem("Unknown 8 FF's", "??", fpos + footerstartpos) { length = 8 }); fpos += 0x8; //ScriptFooterBlocks.Add(new ScriptHeaderItem("Label Table Offset", "??", fpos + footerstartpos) { length = 2 }); fpos += 0x2; var stateFlagsBytes = footerdata.Slice(fpos, 0x4); var stateFlags = (StateFlags)EndianReader.ToInt32(stateFlagsBytes, 0, export.FileRef.Endian); var names = stateFlags.ToString().Split(new[] { ',', ' ' }, StringSplitOptions.RemoveEmptyEntries); fpos += 0x4; var numMappedFunctions = EndianReader.ToInt32(footerdata, fpos, export.FileRef.Endian); fpos += 4; for (int i = 0; i < numMappedFunctions; i++) { var name = EndianReader.ToInt32(footerdata, fpos, export.FileRef.Endian); var uindex = EndianReader.ToInt32(footerdata, fpos + 8, export.FileRef.Endian); var funcMapText = $"{export.FileRef.GetNameEntry(name)} => {export.FileRef.GetEntry(uindex)?.FullPath}()"; fpos += 12; } } } else if (export.FileRef.Game == MEGame.ME1 || export.FileRef.Game == MEGame.ME2) { //Header int pos = 16; var nextItemCompilingChain = EndianReader.ToInt32(data, pos, export.FileRef.Endian); //ScriptHeaderBlocks.Add(new ScriptHeaderItem("Next item in loading chain", nextItemCompilingChain, pos, nextItemCompilingChain > 0 ? export : null)); pos += 8; nextItemCompilingChain = EndianReader.ToInt32(data, pos, export.FileRef.Endian); //ScriptHeaderBlocks.Add(new ScriptHeaderItem("Children Probe Start", nextItemCompilingChain, pos, nextItemCompilingChain > 0 ? export : null)); pos += 8; var line = EndianReader.ToInt32(data, pos, export.FileRef.Endian); //ScriptHeaderBlocks.Add(new ScriptHeaderItem("Line", EndianReader.ToInt32(data, pos, export.FileRef.Endian), pos)); pos += 4; //EndianReader.ToInt32(data, pos, export.FileRef.Endian) //ScriptHeaderBlocks.Add(new ScriptHeaderItem("TextPos", EndianReader.ToInt32(data, pos, export.FileRef.Endian), pos)); pos += 4; int scriptSize = EndianReader.ToInt32(data, pos, export.FileRef.Endian); //ScriptHeaderBlocks.Add(new ScriptHeaderItem("Script Size", scriptSize, pos)); pos += 4; var BytecodeStart = pos; var func = export.ClassName == "State" ? UE3FunctionReader.ReadState(export, data) : UE3FunctionReader.ReadFunction(export, data); func.Decompile(new TextBuilder(), false); //parse bytecode bool defined = func.HasFlag("Defined"); //if (defined) //{ // DecompiledScriptBlocks.Add(func.FunctionSignature + " {"); //} //else //{ // //DecompiledScriptBlocks.Add(func.FunctionSignature); //} for (int i = 0; i < func.Statements.statements.Count; i++) { Statement s = func.Statements.statements[i]; s.SetPaddingForScriptSize(scriptSize); if (s.Reader != null && i == 0) { //Add tokens read from statement. All of them point to the same reader, so just do only the first one. s.Reader.ReadTokens.Select(x => x.ToBytecodeSingularToken(pos)).OrderBy(x => x.StartPos); } } //if (defined) //{ // DecompiledScriptBlocks.Add("}"); //} //Footer pos = data.Length - (func.HasFlag("Net") ? 17 : 15); string flagStr = func.GetFlags(); //ScriptFooterBlocks.Add(new ScriptHeaderItem("Native Index", EndianReader.ToInt16(data, pos, export.FileRef.Endian), pos)); pos += 2; //ScriptFooterBlocks.Add(new ScriptHeaderItem("Operator Precedence", data[pos], pos)); pos++; int functionFlags = EndianReader.ToInt32(data, pos, export.FileRef.Endian); //ScriptFooterBlocks.Add(new ScriptHeaderItem("Flags", $"0x{functionFlags:X8} {flagStr}", pos)); pos += 4; //if ((functionFlags & func._flagSet.GetMask("Net")) != 0) //{ //ScriptFooterBlocks.Add(new ScriptHeaderItem("Unknown 1 (RepOffset?)", EndianReader.ToInt16(data, pos, export.FileRef.Endian), pos)); //pos += 2; //} int friendlyNameIndex = EndianReader.ToInt32(data, pos, export.FileRef.Endian); var friendlyName = export.FileRef.GetNameEntry(friendlyNameIndex); //ScriptFooterBlocks.Add(new ScriptHeaderItem("Friendly Name", Pcc.GetNameEntry(friendlyNameIndex), pos) { length = 8 }); pos += 8; //ME1Explorer.Unreal.Classes.Function func = new ME1Explorer.Unreal.Classes.Function(data, export.FileRef as ME1Package); //try //{ // Function_TextBox.Text = func.ToRawText(); //} //catch (Exception e) //{ // Function_TextBox.Text = "Error parsing function: " + e.Message; //} } else { //Function_TextBox.Text = "Parsing UnrealScript Functions for this game is not supported."; } } //} } } }
public SoundPath(EndianReader reader) { FirstPointIndex = reader.ReadInt32(); PointCount = reader.ReadInt32(); }
public override void Read(EndianReader br) { R = br.ReadSingle(); G = br.ReadSingle(); B = br.ReadSingle(); }
public override void Read(EndianReader br, int Magic) { Read(br); }
// Meta Sorting private void LoadPatch(bool isAlteration) { try { using (var reader = new EndianReader(File.OpenRead(txtApplyPatchFile.Text), Endian.LittleEndian)) { string magic = reader.ReadAscii(4); reader.SeekTo(0); if (magic == "asmp") { // Load into UI reader.Endianness = Endian.BigEndian; currentPatch = AssemblyPatchLoader.LoadPatch(reader); txtApplyPatchAuthor.Text = currentPatch.Author; txtApplyPatchDesc.Text = currentPatch.Description; txtApplyPatchName.Text = currentPatch.Name; txtApplyPatchInternalName.Text = currentPatch.MapInternalName; //txtApplyPatchMapID.Text = currentPatch.MapID.ToString(CultureInfo.InvariantCulture); // Set Visibility PatchApplicationPatchExtra.Visibility = currentPatch.CustomBlfContent != null ? Visibility.Visible : Visibility.Collapsed; ApplyPatchControls.Visibility = Visibility.Visible; btnExtractInfo.IsEnabled = true; } else { currentPatch = OldPatchLoader.LoadPatch(reader, isAlteration); txtApplyPatchAuthor.Text = currentPatch.Author; txtApplyPatchDesc.Text = currentPatch.Description; txtApplyPatchName.Text = "Ascension/Alteration Patch"; txtApplyPatchInternalName.Text = "Ascension/Alteration Patch"; ApplyPatchControls.Visibility = Visibility.Visible; PatchApplicationPatchExtra.Visibility = Visibility.Collapsed; btnExtractInfo.IsEnabled = false; } } // Set Screenshot if (currentPatch.Screenshot == null) { // Set default var source = new Uri(@"/Assembly;component/Metro/Images/super_patcher.png", UriKind.Relative); imgApplyPreview.Source = new BitmapImage(source); } else { var image = new BitmapImage(); image.BeginInit(); image.StreamSource = new MemoryStream(currentPatch.Screenshot); image.EndInit(); imgApplyPreview.Source = image; } } catch (Exception ex) { MetroException.Show(ex); } }
protected void LoadFixups() { var Entry = cache.zone.RawEntries[geomRawID & ushort.MaxValue]; var reader = new EndianReader(new MemoryStream(cache.zone.FixupData), EndianFormat.BigEndian); reader.SeekTo(Entry.FixupOffset + (Entry.FixupSize - 24)); int vCount = reader.ReadInt32(); reader.Skip(8); int iCount = reader.ReadInt32(); reader.SeekTo(Entry.FixupOffset); for (int i = 0; i < vCount; i++) { VertInfoList.Add(new mode.VertexBufferInfo() { Offset = Entry.Fixups[i].Offset, VertexCount = reader.ReadInt32(), Unknown1 = reader.ReadInt32(), DataLength = reader.ReadInt32(), Unknown2 = reader.ReadInt32(), //blank from here so far Unknown3 = reader.ReadInt32(), Unknown4 = reader.ReadInt32(), Unknown5 = reader.ReadInt32(), }); } for (int i = 0; i < vCount; i++) { //assumed to be vertex related Unknown1List.Add(new mode.UnknownInfo1() { Unknown1 = reader.ReadInt32(), //always 0 so far Unknown2 = reader.ReadInt32(), //always 0 so far Unknown3 = reader.ReadInt32(), //1350707457 }); } for (int i = 0; i < iCount; i++) { var data = new mode.IndexBufferInfo(); data.Offset = Entry.Fixups[vCount * 2 + i].Offset; data.FaceFormat = reader.ReadInt32(); //value exists only in reach beta and newer if (cache.Version >= DefinitionSet.HaloReachBeta) data.UnknownX = reader.ReadInt32(); else data.UnknownX = -1; data.DataLength = reader.ReadInt32(); data.Unknown0 = reader.ReadInt32(); //blank from here so far data.Unknown1 = reader.ReadInt32(); data.Unknown2 = reader.ReadInt32(); data.Unknown3 = reader.ReadInt32(); IndexInfoList.Add(data); } for (int i = 0; i < iCount; i++) { //assumed to be index related Unknown2List.Add(new mode.UnknownInfo2() { Unknown1 = reader.ReadInt32(), //always 0 so far Unknown2 = reader.ReadInt32(), //always 0 so far Unknown3 = reader.ReadInt32(), //1753688321 }); } for (int i = 0; i < 4; i++) { Unknown3List.Add(new mode.UnknownInfo3() { Unknown1 = reader.ReadInt32(), //vCount in 3rd, iCount in 4th Unknown2 = reader.ReadInt32(), //always 0 so far Unknown3 = reader.ReadInt32(), }); } reader.Close(); reader.Dispose(); }
public override Bitmap DecodeImage(Stream stream, uint width, uint height) { Bitmap image = new Bitmap((int)width, (int)height); EndianReader reader = new EndianReader(stream, Endianness.BigEndian); for (int y = 0; y < height; y += 8) { for (int x = 0; x < width; x += 8) { for (int y2 = 0; y2 < 8; y2 += 4) { for (int x2 = 0; x2 < 8; x2 += 4) { u16 c0 = reader.ReadUInt16(); u16 c1 = reader.ReadUInt16(); u32 bits = reader.ReadUInt32(); u8 b0 = (u8)((c0 & 0x1f) << 3); u8 g0 = (u8)(((c0 >> 5) & 0x3f) << 2); u8 r0 = (u8)(((c0 >> 11) & 0x1f) << 3); u8 b1 = (u8)((c1 & 0x1f) << 3); u8 g1 = (u8)(((c1 >> 5) & 0x3f) << 2); u8 r1 = (u8)(((c1 >> 11) & 0x1f) << 3); for (int y3 = 3; y3 >= 0; y3--) { for (int x3 = 3; x3 >= 0; x3--) { int newx = x + x2 + x3; int newy = y + y2 + y3; if (newx >= width || newy >= height) { continue; } uint control = bits & 3; bits >>= 2; Color colour; switch (control) { case 0: colour = Color.FromArgb(255, r0, g0, b0); break; case 1: colour = Color.FromArgb(255, r1, g1, b1); break; case 2: if (c0 > c1) { colour = Color.FromArgb(255, (2 * r0 + r1) / 3, (2 * g0 + g1) / 3, (2 * b0 + b1) / 3); } else { colour = Color.FromArgb(255, (r0 + r1) / 2, (g0 + g1) / 2, (b0 + b1) / 2); } break; case 3: if (c0 > c1) { colour = Color.FromArgb(255, (r0 + 2 * r1) / 3, (g0 + 2 * g1) / 3, (b0 + 2 * b1) / 3); } else { colour = Color.FromArgb(255, 0, 0, 0); } break; default: continue; } image.SetPixel(newx, newy, colour); } } } } } } return(image); }
public override void LoadRaw() { if (RawLoaded) return; var data = cache.GetRawFromID(geomRawID); var ms = new MemoryStream(data); var reader = new EndianReader(ms, EndianFormat.BigEndian); var validParts = new Dictionary<int, mode.ModelSection>(); LoadFixups(); #region Read Vertices for (int i = 0; i < ModelSections.Count; i++) { var section = ModelSections[i]; if (section.Submeshes.Count == 0) continue; if (section.VertsIndex >= 0 && section.VertsIndex < VertInfoList.Count) reader.SeekTo(VertInfoList[section.VertsIndex].Offset); if (cache.vertexNode == null) throw new NotSupportedException("No vertex definitions found for " + cache.Version.ToString()); #region Get Vertex Definition XmlNode formatNode = null; foreach (XmlNode node in cache.vertexNode.ChildNodes) { if (Convert.ToInt32(node.Attributes["type"].Value, 16) == section.VertexFormat) { formatNode = node; break; } } if (formatNode == null) throw new NotSupportedException("Format " + section.VertexFormat.ToString() + " not found in definition for " + cache.Version.ToString()); #endregion mode.ModelSection validPart; if (validParts.TryGetValue(section.VertsIndex, out validPart)) { section.Vertices = validPart.Vertices; continue; } else validParts.Add(section.VertsIndex, section); section.Vertices = new Vertex[VertInfoList[section.VertsIndex].VertexCount]; #region Get Vertices for (int j = 0; j < VertInfoList[section.VertsIndex].VertexCount; j++) { mode.BoundingBox bb; section.Vertices[j] = new Vertex(reader, formatNode); if (i >= BoundingBoxes.Count) { bb = new mode.BoundingBox(); bb.XBounds = bb.YBounds = bb.ZBounds = bb.UBounds = bb.VBounds = new RealBounds(0, 0); } else bb = BoundingBoxes[i]; ModelFunctions.DecompressVertex(ref section.Vertices[j], bb); } #endregion } #endregion validParts.Clear(); #region Read Indices for (int i = 0; i < ModelSections.Count; i++) { var section = ModelSections[i]; if (section.Submeshes.Count == 0) continue; if (section.FacesIndex >= 0 && section.FacesIndex < IndexInfoList.Count) reader.SeekTo(IndexInfoList[section.FacesIndex].Offset); mode.ModelSection validPart; if (validParts.TryGetValue(section.FacesIndex, out validPart)) { section.Indices = validPart.Indices; continue; } else validParts.Add(section.FacesIndex, section); section.Indices = new int[section.TotalFaceCount]; for (int j = 0; j < section.TotalFaceCount; j++) section.Indices[j] = (VertInfoList[section.VertsIndex].VertexCount > 0xFFFF) ? reader.ReadInt32() : reader.ReadUInt16(); } #endregion RawLoaded = true; }
public void Versions02(ByteOrder order) { var rng = new Random(); using (var stream = new MemoryStream()) using (var reader = new EndianReader(stream, order)) using (var writer = new EndianWriter(stream, order)) { var rand = new object[5]; rand[0] = rng.Next(int.MinValue, int.MaxValue); writer.Write((int)rand[0]); writer.Write(0); rand[1] = (float)rng.NextDouble(); writer.Write((float)rand[1]); rand[2] = (float)rng.NextDouble(); writer.Write((float)rand[2]); rand[3] = (float)rng.NextDouble(); writer.Write((float)rand[3]); rand[4] = rng.NextDouble(); writer.Write((double)rand[4]); stream.Position = 0; var obj = (DataClass10)reader.ReadObject(typeof(DataClass10), 1); Assert.AreEqual(rand[0], obj.Property1); Assert.AreEqual(0, obj.Version); Assert.AreEqual(rand[1], obj.Property2); Assert.IsNull(obj.Property3); Assert.IsNull(obj.Property4); stream.Position = 0; obj = (DataClass10)reader.ReadObject(typeof(DataClass10), 2); Assert.AreEqual(rand[0], obj.Property1); Assert.AreEqual(0, obj.Version); Assert.AreEqual(rand[2], obj.Property2); Assert.AreEqual(rand[3], obj.Property3); Assert.IsNull(obj.Property4); stream.Position = 0; obj = (DataClass10)reader.ReadObject(typeof(DataClass10), 3); Assert.AreEqual(rand[0], obj.Property1); Assert.AreEqual(0, obj.Version); Assert.AreEqual(rand[2], obj.Property2); Assert.AreEqual(rand[3], obj.Property3); Assert.IsNull(obj.Property4); stream.Position = 0; obj = (DataClass10)reader.ReadObject(typeof(DataClass10), 4); Assert.AreEqual(rand[0], obj.Property1); Assert.AreEqual(0, obj.Version); Assert.AreEqual(rand[2], obj.Property2); Assert.IsNull(obj.Property3); Assert.AreEqual(rand[4], obj.Property4); } }
public static void AssertBinary(ArraySegment <byte> actualBytes, Endianness endianess, params object[] expectedContent) { var str = SegmentToString(actualBytes); using (var stream = actualBytes.AsStream()) { var reader = new EndianReader(stream, endianess); foreach (var expectedObject in expectedContent) { var index = stream.Position; var type = expectedObject.GetType(); if (type == typeof(uint)) { var expected = (uint)expectedObject; var actual = reader.ReadUInt32(); Check.That(actual).IsEqualTo(expected); } else if (type == typeof(ushort)) { var expected = (ushort)expectedObject; var actual = reader.ReadUInt16(); Check.That(actual).IsEqualTo(expected); } else if (type == typeof(byte)) { var expected = (byte)expectedObject; var actual = reader.ReadByte(); if (actual != expected) { throw new AssertionException( $"Byte at index {index} is 0x{actual:X2} but 0x{expected:X2} was expected.\r\n\r\n{str}"); } } else if (type == typeof(BytesHolder)) { var holder = (BytesHolder)expectedObject; reader.Read(holder.Bytes, 0, holder.ByteCount); } else if (type == typeof(ArraySegment <byte>)) { var expected = (ArraySegment <byte>)expectedObject; var actual = new byte[expected.Count]; reader.Read(actual, 0, actual.Length); Check.That(expected.ContentEquals(actual.Segment())).IsTrue(); } else if (type == typeof(byte[])) { var expected = (byte[])expectedObject; var actual = new byte[expected.Length]; reader.Read(actual, 0, actual.Length); if (!expected.Segment().ContentEquals(actual.Segment())) { var actualStr = SegmentToString(actual.Segment()); var expectedStr = SegmentToString(expected.Segment()); throw new AssertionException($"The 2 binary data differ, expected: \r\n{expectedStr}\r\nRead:\r\n{actualStr}\r\nFull actual data:\r\n{str}"); } } } } }
public render_model(CacheBase Cache, int Address) { cache = Cache; EndianReader Reader = Cache.Reader; Reader.SeekTo(Address); Name = Cache.Strings.GetItemByID(Reader.ReadInt32()); Flags = new Bitmask(Reader.ReadInt32()); #region Regions Block Reader.SeekTo(Address + 12); int iCount = Reader.ReadInt32(); int iOffset = Reader.ReadInt32() - Cache.Magic; for (int i = 0; i < iCount; i++) { Regions.Add(new Region(Cache, iOffset + 16 * i)); } #endregion Reader.SeekTo(Address + 28); InstancedGeometryIndex = Reader.ReadInt32(); #region Instanced Geometry Block Reader.SeekTo(Address + 32); iCount = Reader.ReadInt32(); iOffset = Reader.ReadInt32() - Cache.Magic; for (int i = 0; i < iCount; i++) { GeomInstances.Add(new InstancedGeometry(Cache, iOffset + 60 * i)); } #endregion #region Nodes Block Reader.SeekTo(Address + 48); iCount = Reader.ReadInt32(); iOffset = Reader.ReadInt32() - Cache.Magic; for (int i = 0; i < iCount; i++) { Nodes.Add(new Node(Cache, iOffset + 112 * i)); } #endregion #region MarkerGroups Block Reader.SeekTo(Address + 60); iCount = Reader.ReadInt32(); iOffset = Reader.ReadInt32() - Cache.Magic; for (int i = 0; i < iCount; i++) { MarkerGroups.Add(new MarkerGroup(Cache, iOffset + 16 * i)); } #endregion #region Shaders Block Reader.SeekTo(Address + 72); iCount = Reader.ReadInt32(); iOffset = Reader.ReadInt32() - Cache.Magic; for (int i = 0; i < iCount; i++) { Shaders.Add(new Shader(Cache, iOffset + 44 * i)); } #endregion #region ModelParts Block Reader.SeekTo(Address + 104); iCount = Reader.ReadInt32(); iOffset = Reader.ReadInt32() - Cache.Magic; for (int i = 0; i < iCount; i++) { ModelSections.Add(new ModelSection(Cache, iOffset + 112 * i)); } #endregion #region BoundingBox Block Reader.SeekTo(Address + 128); iCount = Reader.ReadInt32(); iOffset = Reader.ReadInt32() - Cache.Magic; for (int i = 0; i < iCount; i++) { BoundingBoxes.Add(new BoundingBox(Cache, iOffset + 52 * i)); } #endregion #region NodeMapGroup Block Reader.SeekTo(Address + 188); iCount = Reader.ReadInt32(); iOffset = Reader.ReadInt32() - Cache.Magic; for (int i = 0; i < iCount; i++) { NodeIndexGroups.Add(new NodeIndexGroup(Cache, iOffset + 12 * i)); } #endregion Reader.SeekTo(Address + 248); RawID = Reader.ReadInt32(); }
internal override void DeserializeData(EndianReader reader) { Flags = reader.ReadUInt32LE(); }
public override object Execute(List <string> args) { // Deserialize the definition data var resourceContext = new ResourceSerializationContext(CacheContext, BSP.CollisionBspResource); var definition = CacheContext.Deserializer.Deserialize <StructureBspTagResources>(resourceContext); // Extract the resource data var resourceDataStream = new MemoryStream(); CacheContext.ExtractResource(BSP.CollisionBspResource, resourceDataStream); using (var reader = new EndianReader(resourceDataStream)) { #region collision bsps foreach (var cbsp in definition.CollisionBsps) { reader.BaseStream.Position = cbsp.Bsp3dNodes.Address.Offset; for (var i = 0; i < cbsp.Bsp3dNodes.Count; i++) { var element = CacheContext.Deserializer.DeserializeValue(reader, null, null, typeof(CollisionGeometry.Bsp3dNode)); cbsp.Bsp3dNodes.Add((CollisionGeometry.Bsp3dNode)element); } reader.BaseStream.Position = cbsp.Planes.Address.Offset; for (var i = 0; i < cbsp.Planes.Count; i++) { var element = CacheContext.Deserializer.DeserializeValue(reader, null, null, typeof(CollisionGeometry.Plane)); cbsp.Planes.Add((CollisionGeometry.Plane)element); } reader.BaseStream.Position = cbsp.Leaves.Address.Offset; for (var i = 0; i < cbsp.Leaves.Count; i++) { var element = CacheContext.Deserializer.DeserializeValue(reader, null, null, typeof(CollisionGeometry.Leaf)); cbsp.Leaves.Add((CollisionGeometry.Leaf)element); } reader.BaseStream.Position = cbsp.Bsp2dReferences.Address.Offset; for (var i = 0; i < cbsp.Bsp2dReferences.Count; i++) { var element = CacheContext.Deserializer.DeserializeValue(reader, null, null, typeof(CollisionGeometry.Bsp2dReference)); cbsp.Bsp2dReferences.Add((CollisionGeometry.Bsp2dReference)element); } reader.BaseStream.Position = cbsp.Bsp2dNodes.Address.Offset; for (var i = 0; i < cbsp.Bsp2dNodes.Count; i++) { var element = CacheContext.Deserializer.DeserializeValue(reader, null, null, typeof(CollisionGeometry.Bsp2dNode)); cbsp.Bsp2dNodes.Add((CollisionGeometry.Bsp2dNode)element); } reader.BaseStream.Position = cbsp.Surfaces.Address.Offset; for (var i = 0; i < cbsp.Surfaces.Count; i++) { var element = CacheContext.Deserializer.DeserializeValue(reader, null, null, typeof(CollisionGeometry.Surface)); cbsp.Surfaces.Add((CollisionGeometry.Surface)element); } reader.BaseStream.Position = cbsp.Edges.Address.Offset; for (var i = 0; i < cbsp.Edges.Count; i++) { var element = CacheContext.Deserializer.DeserializeValue(reader, null, null, typeof(CollisionGeometry.Edge)); cbsp.Edges.Add((CollisionGeometry.Edge)element); } reader.BaseStream.Position = cbsp.Vertices.Address.Offset; for (var i = 0; i < cbsp.Vertices.Count; i++) { var element = CacheContext.Deserializer.DeserializeValue(reader, null, null, typeof(CollisionGeometry.Vertex)); cbsp.Vertices.Add((CollisionGeometry.Vertex)element); } } #endregion #region large collision bsps foreach (var cbsp in definition.LargeCollisionBsps) { reader.BaseStream.Position = cbsp.Bsp3dNodes.Address.Offset; for (var i = 0; i < cbsp.Bsp3dNodes.Count; i++) { var element = CacheContext.Deserializer.DeserializeValue(reader, null, null, typeof(StructureBspTagResources.LargeCollisionBspBlock.Bsp3dNode)); cbsp.Bsp3dNodes.Add((StructureBspTagResources.LargeCollisionBspBlock.Bsp3dNode)element); } reader.BaseStream.Position = cbsp.Planes.Address.Offset; for (var i = 0; i < cbsp.Planes.Count; i++) { var element = CacheContext.Deserializer.DeserializeValue(reader, null, null, typeof(CollisionGeometry.Plane)); cbsp.Planes.Add((CollisionGeometry.Plane)element); } reader.BaseStream.Position = cbsp.Leaves.Address.Offset; for (var i = 0; i < cbsp.Leaves.Count; i++) { var element = CacheContext.Deserializer.DeserializeValue(reader, null, null, typeof(CollisionGeometry.Leaf)); cbsp.Leaves.Add((CollisionGeometry.Leaf)element); } reader.BaseStream.Position = cbsp.Bsp2dReferences.Address.Offset; for (var i = 0; i < cbsp.Bsp2dReferences.Count; i++) { var element = CacheContext.Deserializer.DeserializeValue(reader, null, null, typeof(StructureBspTagResources.LargeCollisionBspBlock.Bsp2dReference)); cbsp.Bsp2dReferences.Add((StructureBspTagResources.LargeCollisionBspBlock.Bsp2dReference)element); } reader.BaseStream.Position = cbsp.Bsp2dNodes.Address.Offset; for (var i = 0; i < cbsp.Bsp2dNodes.Count; i++) { var element = CacheContext.Deserializer.DeserializeValue(reader, null, null, typeof(StructureBspTagResources.LargeCollisionBspBlock.Bsp2dNode)); cbsp.Bsp2dNodes.Add((StructureBspTagResources.LargeCollisionBspBlock.Bsp2dNode)element); } reader.BaseStream.Position = cbsp.Surfaces.Address.Offset; for (var i = 0; i < cbsp.Surfaces.Count; i++) { var element = CacheContext.Deserializer.DeserializeValue(reader, null, null, typeof(StructureBspTagResources.LargeCollisionBspBlock.Surface)); cbsp.Surfaces.Add((StructureBspTagResources.LargeCollisionBspBlock.Surface)element); } reader.BaseStream.Position = cbsp.Edges.Address.Offset; for (var i = 0; i < cbsp.Edges.Count; i++) { var element = CacheContext.Deserializer.DeserializeValue(reader, null, null, typeof(StructureBspTagResources.LargeCollisionBspBlock.Edge)); cbsp.Edges.Add((StructureBspTagResources.LargeCollisionBspBlock.Edge)element); } reader.BaseStream.Position = cbsp.Vertices.Address.Offset; for (var i = 0; i < cbsp.Vertices.Count; i++) { var element = CacheContext.Deserializer.DeserializeValue(reader, null, null, typeof(StructureBspTagResources.LargeCollisionBspBlock.Vertex)); cbsp.Vertices.Add((StructureBspTagResources.LargeCollisionBspBlock.Vertex)element); } } #endregion #region compressions foreach (var instance in definition.InstancedGeometry) { #region compression's resource data reader.BaseStream.Position = instance.CollisionInfo.Bsp3dNodes.Address.Offset; for (var i = 0; i < instance.CollisionInfo.Bsp3dNodes.Count; i++) { var element = CacheContext.Deserializer.DeserializeValue(reader, null, null, typeof(CollisionGeometry.Bsp3dNode)); instance.CollisionInfo.Bsp3dNodes.Add((CollisionGeometry.Bsp3dNode)element); } reader.BaseStream.Position = instance.CollisionInfo.Planes.Address.Offset; for (var i = 0; i < instance.CollisionInfo.Planes.Count; i++) { var element = CacheContext.Deserializer.DeserializeValue(reader, null, null, typeof(CollisionGeometry.Plane)); instance.CollisionInfo.Planes.Add((CollisionGeometry.Plane)element); } reader.BaseStream.Position = instance.CollisionInfo.Leaves.Address.Offset; for (var i = 0; i < instance.CollisionInfo.Leaves.Count; i++) { var element = CacheContext.Deserializer.DeserializeValue(reader, null, null, typeof(CollisionGeometry.Leaf)); instance.CollisionInfo.Leaves.Add((CollisionGeometry.Leaf)element); } reader.BaseStream.Position = instance.CollisionInfo.Bsp2dReferences.Address.Offset; for (var i = 0; i < instance.CollisionInfo.Bsp2dReferences.Count; i++) { var element = CacheContext.Deserializer.DeserializeValue(reader, null, null, typeof(CollisionGeometry.Bsp2dReference)); instance.CollisionInfo.Bsp2dReferences.Add((CollisionGeometry.Bsp2dReference)element); } reader.BaseStream.Position = instance.CollisionInfo.Bsp2dNodes.Address.Offset; for (var i = 0; i < instance.CollisionInfo.Bsp2dNodes.Count; i++) { var element = CacheContext.Deserializer.DeserializeValue(reader, null, null, typeof(CollisionGeometry.Bsp2dNode)); instance.CollisionInfo.Bsp2dNodes.Add((CollisionGeometry.Bsp2dNode)element); } reader.BaseStream.Position = instance.CollisionInfo.Surfaces.Address.Offset; for (var i = 0; i < instance.CollisionInfo.Surfaces.Count; i++) { var element = CacheContext.Deserializer.DeserializeValue(reader, null, null, typeof(CollisionGeometry.Surface)); instance.CollisionInfo.Surfaces.Add((CollisionGeometry.Surface)element); } reader.BaseStream.Position = instance.CollisionInfo.Edges.Address.Offset; for (var i = 0; i < instance.CollisionInfo.Edges.Count; i++) { var element = CacheContext.Deserializer.DeserializeValue(reader, null, null, typeof(CollisionGeometry.Edge)); instance.CollisionInfo.Edges.Add((CollisionGeometry.Edge)element); } reader.BaseStream.Position = instance.CollisionInfo.Vertices.Address.Offset; for (var i = 0; i < instance.CollisionInfo.Vertices.Count; i++) { var element = CacheContext.Deserializer.DeserializeValue(reader, null, null, typeof(CollisionGeometry.Vertex)); instance.CollisionInfo.Vertices.Add((CollisionGeometry.Vertex)element); } #endregion #region compression's other resource data foreach (var cbsp in instance.CollisionGeometries) { reader.BaseStream.Position = cbsp.Bsp3dNodes.Address.Offset; for (var i = 0; i < cbsp.Bsp3dNodes.Count; i++) { var element = CacheContext.Deserializer.DeserializeValue(reader, null, null, typeof(CollisionGeometry.Bsp3dNode)); cbsp.Bsp3dNodes.Add((CollisionGeometry.Bsp3dNode)element); } reader.BaseStream.Position = cbsp.Planes.Address.Offset; for (var i = 0; i < cbsp.Planes.Count; i++) { var element = CacheContext.Deserializer.DeserializeValue(reader, null, null, typeof(CollisionGeometry.Plane)); cbsp.Planes.Add((CollisionGeometry.Plane)element); } reader.BaseStream.Position = cbsp.Leaves.Address.Offset; for (var i = 0; i < cbsp.Leaves.Count; i++) { var element = CacheContext.Deserializer.DeserializeValue(reader, null, null, typeof(CollisionGeometry.Leaf)); cbsp.Leaves.Add((CollisionGeometry.Leaf)element); } reader.BaseStream.Position = cbsp.Bsp2dReferences.Address.Offset; for (var i = 0; i < cbsp.Bsp2dReferences.Count; i++) { var element = CacheContext.Deserializer.DeserializeValue(reader, null, null, typeof(CollisionGeometry.Bsp2dReference)); cbsp.Bsp2dReferences.Add((CollisionGeometry.Bsp2dReference)element); } reader.BaseStream.Position = cbsp.Bsp2dNodes.Address.Offset; for (var i = 0; i < cbsp.Bsp2dNodes.Count; i++) { var element = CacheContext.Deserializer.DeserializeValue(reader, null, null, typeof(CollisionGeometry.Bsp2dNode)); cbsp.Bsp2dNodes.Add((CollisionGeometry.Bsp2dNode)element); } reader.BaseStream.Position = cbsp.Surfaces.Address.Offset; for (var i = 0; i < cbsp.Surfaces.Count; i++) { var element = CacheContext.Deserializer.DeserializeValue(reader, null, null, typeof(CollisionGeometry.Surface)); cbsp.Surfaces.Add((CollisionGeometry.Surface)element); } reader.BaseStream.Position = cbsp.Edges.Address.Offset; for (var i = 0; i < cbsp.Edges.Count; i++) { var element = CacheContext.Deserializer.DeserializeValue(reader, null, null, typeof(CollisionGeometry.Edge)); cbsp.Edges.Add((CollisionGeometry.Edge)element); } reader.BaseStream.Position = cbsp.Vertices.Address.Offset; for (var i = 0; i < cbsp.Vertices.Count; i++) { var element = CacheContext.Deserializer.DeserializeValue(reader, null, null, typeof(CollisionGeometry.Vertex)); cbsp.Vertices.Add((CollisionGeometry.Vertex)element); } } #endregion #region Unknown Data for (var i = 0; i < instance.Unknown1.Count; i++) { var element = CacheContext.Deserializer.DeserializeValue(reader, null, null, typeof(StructureBspTagResources.InstancedGeometryBlock.Unknown1Block)); instance.Unknown1.Add((StructureBspTagResources.InstancedGeometryBlock.Unknown1Block)element); } for (var i = 0; i < instance.Unknown2.Count; i++) { var element = CacheContext.Deserializer.DeserializeValue(reader, null, null, typeof(StructureBspTagResources.InstancedGeometryBlock.Unknown2Block)); instance.Unknown2.Add((StructureBspTagResources.InstancedGeometryBlock.Unknown2Block)element); } for (var i = 0; i < instance.Unknown3.Count; i++) { var element = CacheContext.Deserializer.DeserializeValue(reader, null, null, typeof(StructureBspTagResources.InstancedGeometryBlock.Unknown3Block)); instance.Unknown3.Add((StructureBspTagResources.InstancedGeometryBlock.Unknown3Block)element); } #endregion #region compression's havok collision data foreach (var collision in instance.BspPhysics) { for (var i = 0; i < collision.Data.Count; i++) { var element = CacheContext.Deserializer.DeserializeValue(reader, null, null, typeof(byte)); collision.Data.Add(new StructureBspTagResources.CollisionBspPhysicsBlock.Datum { Value = (byte)element }); } } #endregion } #endregion } return(true); }
public override void Read(EndianReader br) { Tag = (Index = Id = br.ReadInt32()) != -1 ? ((Dictionary <string, int>)EngineManager.Engines[Global.Application.Instance.Project.Engine]["TagIds"]).Keys.ElementAt(Index) : "Null Reference"; }
public CacheHeader(CacheBase Cache) { cache = Cache; EndianReader Reader = cache.Reader; #region Read Values XmlNode headerNode = cache.versionNode.ChildNodes[0]; XmlAttribute attr = headerNode.Attributes["fileSize"]; int offset = int.Parse(attr.Value); Reader.SeekTo(offset); fileSize = Reader.ReadInt32(); attr = headerNode.Attributes["indexOffset"]; offset = int.Parse(attr.Value); Reader.SeekTo(offset); indexOffset = Reader.ReadInt32(); attr = headerNode.Attributes["tagDataAddress"]; offset = int.Parse(attr.Value); Reader.SeekTo(offset); tagDataAddress = Reader.ReadInt32(); attr = headerNode.Attributes["stringCount"]; offset = int.Parse(attr.Value); Reader.SeekTo(offset); stringCount = Reader.ReadInt32(); attr = headerNode.Attributes["stringTableSize"]; offset = int.Parse(attr.Value); Reader.SeekTo(offset); stringTableSize = Reader.ReadInt32(); attr = headerNode.Attributes["stringTableIndexOffset"]; offset = int.Parse(attr.Value); Reader.SeekTo(offset); stringTableIndexOffset = Reader.ReadInt32(); attr = headerNode.Attributes["stringTableOffset"]; offset = int.Parse(attr.Value); Reader.SeekTo(offset); stringTableOffset = Reader.ReadInt32(); attr = headerNode.Attributes["scenarioName"]; offset = int.Parse(attr.Value); Reader.SeekTo(offset); scenarioName = Reader.ReadString(256); attr = headerNode.Attributes["fileCount"]; offset = int.Parse(attr.Value); Reader.SeekTo(offset); fileCount = Reader.ReadInt32(); attr = headerNode.Attributes["fileTableOffset"]; offset = int.Parse(attr.Value); Reader.SeekTo(offset); fileTableOffset = Reader.ReadInt32(); attr = headerNode.Attributes["fileTableSize"]; offset = int.Parse(attr.Value); Reader.SeekTo(offset); fileTableSize = Reader.ReadInt32(); attr = headerNode.Attributes["fileTableIndexOffset"]; offset = int.Parse(attr.Value); Reader.SeekTo(offset); fileTableIndexOffset = Reader.ReadInt32(); #endregion }
public List <ModelAnimationGraph.ResourceGroup> ConvertModelAnimationGraphResourceGroups(Stream cacheStream, Dictionary <ResourceLocation, Stream> resourceStreams, List <ModelAnimationGraph.ResourceGroup> resourceGroups) { if (BlamCache.ResourceGestalt == null) { BlamCache.LoadResourceTags(); } var resourceDefinition = new List <ModelAnimationTagResource>(); foreach (var group in resourceGroups) { var resourceEntry = BlamCache.ResourceGestalt.TagResources[group.ZoneAssetDatumIndex & ushort.MaxValue]; group.Resource = new PageableResource { Page = new RawPage { Index = -1, }, Resource = new TagResourceGen3 { ResourceType = TagResourceTypeGen3.Animation, DefinitionData = BlamCache.ResourceGestalt.FixupInformation.Skip(resourceEntry.FixupInformationOffset).Take(resourceEntry.FixupInformationLength).ToArray(), DefinitionAddress = resourceEntry.DefinitionAddress, ResourceFixups = new List <TagResourceGen3.ResourceFixup>(), ResourceDefinitionFixups = new List <TagResourceGen3.ResourceDefinitionFixup>(), Unknown2 = 1 } }; // Convert blam fixups // get the list of members in this resourcegroup. this list contains address, various offsets, and other info about the member. if (group.Resource.Resource.DefinitionData.Length != 0) { using (var definitionStream = new MemoryStream(group.Resource.Resource.DefinitionData, true)) using (var definitionReader = new EndianReader(definitionStream, EndianFormat.BigEndian)) using (var definitionWriter = new EndianWriter(definitionStream, EndianFormat.BigEndian)) { foreach (var fixup in resourceEntry.ResourceFixups) { var newFixup = new TagResourceGen3.ResourceFixup { BlockOffset = (uint)fixup.BlockOffset, Address = new CacheAddress(CacheAddressType.Resource, fixup.Offset) }; definitionStream.Position = newFixup.BlockOffset; definitionWriter.Write(newFixup.Address.Value); group.Resource.Resource.ResourceFixups.Add(newFixup); } var dataContext = new DataSerializationContext(definitionReader, definitionWriter, CacheAddressType.Definition); definitionStream.Position = group.Resource.Resource.DefinitionAddress.Offset + 0x4; definitionWriter.Write(0x20000000); // ODST's resource type is 4 when it's supposed to be 2 because the resource definition is in the tag and not as a raw resource definitionStream.Position = group.Resource.Resource.DefinitionAddress.Offset; resourceDefinition.Add(BlamCache.Deserializer.Deserialize <ModelAnimationTagResource>(dataContext)); } } } var diffLines = new List <string>(); var resDefIndex = -1; foreach (var group in resourceGroups) { resDefIndex++; if (resourceDefinition.Count < resDefIndex + 1) { continue; // rare cases, might break the game } // Get the resource group real size, which is probably not in the resource definition var groupSize = 0; foreach (var groupMember in resourceDefinition[resDefIndex].GroupMembers) { groupSize += groupMember.AnimationData.Size; while (groupSize % 0x10 != 0) // align to 0x10. { groupSize += 4; } } var resourceData = BlamCache.GetRawFromID(group.ZoneAssetDatumIndex, groupSize); if (resourceData == null) { return(null); } using (var blamResourceStream = new MemoryStream(resourceData)) using (var resourceReader = new EndianReader(blamResourceStream, EndianFormat.BigEndian)) using (var dataStream = new MemoryStream(new byte[groupSize])) using (var resourceWriter = new EndianWriter(dataStream, EndianFormat.LittleEndian)) { var dataContext = new DataSerializationContext(resourceReader, resourceWriter); var memberIndex = -1; var memberOffset = 0; foreach (var member in resourceDefinition[resDefIndex].GroupMembers) { memberIndex++; ModelAnimationTagResource.GroupMember.Codec codec; ModelAnimationTagResource.GroupMember.FrameInfo frameInfo; if ((byte)member.BaseHeader != 0) { blamResourceStream.Position = member.AnimationData.Address.Offset; dataStream.Position = member.AnimationData.Address.Offset; codec = BlamCache.Deserializer.Deserialize <ModelAnimationTagResource.GroupMember.Codec>(dataContext); CacheContext.Serializer.Serialize(dataContext, codec); var Format1 = BlamCache.Deserializer.Deserialize <ModelAnimationTagResource.GroupMember.Format1>(dataContext); CacheContext.Serializer.Serialize(dataContext, Format1); // blamResourceStream.Position = (long)member.AnimationData.Address.Offset + headerSize; // edResourceStream.Position = blamResourceStream.Position; for (int i = 0; i < codec.RotationNodeCount; i++) { CacheContext.Serializer.Serialize(dataContext, BlamCache.Deserializer.Deserialize <ModelAnimationTagResource.GroupMember.RotationFrame>(dataContext)); } blamResourceStream.Position = member.AnimationData.Address.Offset + Format1.DataStart; dataStream.Position = blamResourceStream.Position; for (int i = 0; i < codec.PositionNodeCount; i++) { CacheContext.Serializer.Serialize(dataContext, BlamCache.Deserializer.Deserialize <ModelAnimationTagResource.GroupMember.PositionFrame>(dataContext)); } blamResourceStream.Position = member.AnimationData.Address.Offset + Format1.ScaleFramesOffset; dataStream.Position = blamResourceStream.Position; for (int i = 0; i < codec.ScaleNodeCount; i++) { CacheContext.Serializer.Serialize(dataContext, BlamCache.Deserializer.Deserialize <ModelAnimationTagResource.GroupMember.ScaleFrame>(dataContext)); } } // If the overlay header is alone, member.OverlayOffset = 0 blamResourceStream.Position = (long)member.AnimationData.Address.Offset + member.OverlayOffset; dataStream.Position = (long)member.AnimationData.Address.Offset + member.OverlayOffset; codec = BlamCache.Deserializer.Deserialize <ModelAnimationTagResource.GroupMember.Codec>(dataContext); CacheContext.Serializer.Serialize(dataContext, codec); // deserialize second header. or as first header if the type1/format1 header isn't used. switch (codec.AnimationCodec) { case ModelAnimationTagResource.AnimationCompressionFormats.Type3: // should merge with type1 var header = BlamCache.Deserializer.Deserialize <ModelAnimationTagResource.GroupMember.Format1>(dataContext); CacheContext.Serializer.Serialize(dataContext, header); for (int nodeIndex = 0; nodeIndex < codec.RotationNodeCount; nodeIndex++) { for (int frameIndex = 0; frameIndex < member.FrameCount; frameIndex++) { CacheContext.Serializer.Serialize(dataContext, BlamCache.Deserializer.Deserialize <ModelAnimationTagResource.GroupMember.RotationFrame>(dataContext)); } } blamResourceStream.Position = (long)member.AnimationData.Address.Offset + member.OverlayOffset + header.DataStart; dataStream.Position = blamResourceStream.Position; for (int nodeIndex = 0; nodeIndex < codec.PositionNodeCount; nodeIndex++) { for (int frameIndex = 0; frameIndex < member.FrameCount; frameIndex++) { CacheContext.Serializer.Serialize(dataContext, BlamCache.Deserializer.Deserialize <ModelAnimationTagResource.GroupMember.PositionFrame>(dataContext)); } } blamResourceStream.Position = (long)member.AnimationData.Address.Offset + member.OverlayOffset + header.ScaleFramesOffset; dataStream.Position = blamResourceStream.Position; for (int nodeIndex = 0; nodeIndex < codec.ScaleNodeCount; nodeIndex++) { for (int frameIndex = 0; frameIndex < member.FrameCount; frameIndex++) { CacheContext.Serializer.Serialize(dataContext, BlamCache.Deserializer.Deserialize <ModelAnimationTagResource.GroupMember.ScaleFrame>(dataContext)); } } break; case ModelAnimationTagResource.AnimationCompressionFormats.Type4: case ModelAnimationTagResource.AnimationCompressionFormats.Type5: case ModelAnimationTagResource.AnimationCompressionFormats.Type6: case ModelAnimationTagResource.AnimationCompressionFormats.Type7: var overlay = BlamCache.Deserializer.Deserialize <ModelAnimationTagResource.GroupMember.Overlay>(dataContext); CacheContext.Serializer.Serialize(dataContext, overlay); #region Description // Description by DemonicSandwich from http://remnantmods.com/forums/viewtopic.php?f=13&t=1574 (matches my previous observations) // Format 6 uses Keyframes the way there are supposed to be used. As KEY frames, with the majority of the frames being Tweens. // // This format adds two extra blocks of data to it's structure. // One block that determines how many Keyframes each Node will have, and an offset to to where it's Markers start from. // // Advantages: // This format requires far fewer Keyframes to make a complex animation. // You do not need a keyframe for each render frame. // Disadvantages: // It's a bit more complex to work with. // Since it's Keyrame Markers are only 1 byte in size, you're animation cannot be longer than 256 frames, or ~8.5 seconds for non - machine objects. > 12 bits for gen3, max 0xFFF frames // Machines are still limited to 256 frames but the frames can be stretched out. #endregion var RotationFrameCount = new List <uint>(); var PositionFrameCount = new List <uint>(); var ScaleFrameCount = new List <uint>(); for (int i = 0; i < codec.RotationNodeCount; i++) { frameInfo = BlamCache.Deserializer.Deserialize <ModelAnimationTagResource.GroupMember.FrameInfo>(dataContext); CacheContext.Serializer.Serialize(dataContext, frameInfo); var keyframesOffset = frameInfo.FrameCount & 0x00FFF000; // unused in this conversion var keyframes = frameInfo.FrameCount & 0x00000FFF; RotationFrameCount.Add(keyframes); } for (int i = 0; i < codec.PositionNodeCount; i++) { frameInfo = BlamCache.Deserializer.Deserialize <ModelAnimationTagResource.GroupMember.FrameInfo>(dataContext); CacheContext.Serializer.Serialize(dataContext, frameInfo); var keyframesOffset = frameInfo.FrameCount & 0x00FFF000; var keyframes = frameInfo.FrameCount & 0x00000FFF; PositionFrameCount.Add(keyframes); } for (int i = 0; i < codec.ScaleNodeCount; i++) { frameInfo = BlamCache.Deserializer.Deserialize <ModelAnimationTagResource.GroupMember.FrameInfo>(dataContext); CacheContext.Serializer.Serialize(dataContext, frameInfo); var keyframesOffset = frameInfo.FrameCount & 0x00FFF000; var keyframes = frameInfo.FrameCount & 0x00000FFF; ScaleFrameCount.Add(keyframes); } blamResourceStream.Position = (long)member.AnimationData.Address.Offset + member.OverlayOffset + overlay.RotationKeyframesOffset; dataStream.Position = blamResourceStream.Position; foreach (var framecount in RotationFrameCount) { for (int i = 0; i < framecount; i++) { if (codec.AnimationCodec == ModelAnimationTagResource.AnimationCompressionFormats.Type4) { CacheContext.Serializer.Serialize(dataContext, BlamCache.Deserializer.Deserialize <ModelAnimationTagResource.GroupMember.Keyframe>(dataContext)); } else if (codec.AnimationCodec == ModelAnimationTagResource.AnimationCompressionFormats.Type5) { CacheContext.Serializer.Serialize(dataContext, BlamCache.Deserializer.Deserialize <ModelAnimationTagResource.GroupMember.KeyframeType5>(dataContext)); } else if (codec.AnimationCodec == ModelAnimationTagResource.AnimationCompressionFormats.Type6) { CacheContext.Serializer.Serialize(dataContext, BlamCache.Deserializer.Deserialize <ModelAnimationTagResource.GroupMember.Keyframe>(dataContext)); } else if (codec.AnimationCodec == ModelAnimationTagResource.AnimationCompressionFormats.Type7) { CacheContext.Serializer.Serialize(dataContext, BlamCache.Deserializer.Deserialize <ModelAnimationTagResource.GroupMember.KeyframeType5>(dataContext)); } } } blamResourceStream.Position = (long)member.AnimationData.Address.Offset + member.OverlayOffset + overlay.PositionKeyframesOffset; dataStream.Position = blamResourceStream.Position; foreach (var framecount in PositionFrameCount) { for (int i = 0; i < framecount; i++) { if (codec.AnimationCodec == ModelAnimationTagResource.AnimationCompressionFormats.Type4) { CacheContext.Serializer.Serialize(dataContext, BlamCache.Deserializer.Deserialize <ModelAnimationTagResource.GroupMember.Keyframe>(dataContext)); } else if (codec.AnimationCodec == ModelAnimationTagResource.AnimationCompressionFormats.Type5) { CacheContext.Serializer.Serialize(dataContext, BlamCache.Deserializer.Deserialize <ModelAnimationTagResource.GroupMember.KeyframeType5>(dataContext)); } else if (codec.AnimationCodec == ModelAnimationTagResource.AnimationCompressionFormats.Type6) { CacheContext.Serializer.Serialize(dataContext, BlamCache.Deserializer.Deserialize <ModelAnimationTagResource.GroupMember.Keyframe>(dataContext)); } else if (codec.AnimationCodec == ModelAnimationTagResource.AnimationCompressionFormats.Type7) { CacheContext.Serializer.Serialize(dataContext, BlamCache.Deserializer.Deserialize <ModelAnimationTagResource.GroupMember.KeyframeType5>(dataContext)); } } } blamResourceStream.Position = (long)member.AnimationData.Address.Offset + member.OverlayOffset + overlay.ScaleKeyframesOffset; dataStream.Position = blamResourceStream.Position; foreach (var framecount in ScaleFrameCount) { for (int i = 0; i < framecount; i++) { if (codec.AnimationCodec == ModelAnimationTagResource.AnimationCompressionFormats.Type4) { CacheContext.Serializer.Serialize(dataContext, BlamCache.Deserializer.Deserialize <ModelAnimationTagResource.GroupMember.Keyframe>(dataContext)); } else if (codec.AnimationCodec == ModelAnimationTagResource.AnimationCompressionFormats.Type5) { CacheContext.Serializer.Serialize(dataContext, BlamCache.Deserializer.Deserialize <ModelAnimationTagResource.GroupMember.KeyframeType5>(dataContext)); } else if (codec.AnimationCodec == ModelAnimationTagResource.AnimationCompressionFormats.Type6) { CacheContext.Serializer.Serialize(dataContext, BlamCache.Deserializer.Deserialize <ModelAnimationTagResource.GroupMember.Keyframe>(dataContext)); } else if (codec.AnimationCodec == ModelAnimationTagResource.AnimationCompressionFormats.Type7) { CacheContext.Serializer.Serialize(dataContext, BlamCache.Deserializer.Deserialize <ModelAnimationTagResource.GroupMember.KeyframeType5>(dataContext)); } } } blamResourceStream.Position = (long)member.AnimationData.Address.Offset + member.OverlayOffset + overlay.RotationFramesOffset; dataStream.Position = blamResourceStream.Position; foreach (var framecount in RotationFrameCount) { for (int i = 0; i < framecount; i++) { CacheContext.Serializer.Serialize(dataContext, BlamCache.Deserializer.Deserialize <ModelAnimationTagResource.GroupMember.RotationFrame>(dataContext)); } } blamResourceStream.Position = (long)member.AnimationData.Address.Offset + member.OverlayOffset + overlay.PositionFramesOffset; dataStream.Position = blamResourceStream.Position; foreach (var framecount in PositionFrameCount) { for (int i = 0; i < framecount; i++) { CacheContext.Serializer.Serialize(dataContext, BlamCache.Deserializer.Deserialize <ModelAnimationTagResource.GroupMember.PositionFrame>(dataContext)); } } blamResourceStream.Position = (long)member.AnimationData.Address.Offset + member.OverlayOffset + overlay.ScaleFramesOffset; dataStream.Position = blamResourceStream.Position; foreach (var framecount in ScaleFrameCount) { for (int i = 0; i < framecount; i++) { CacheContext.Serializer.Serialize(dataContext, BlamCache.Deserializer.Deserialize <ModelAnimationTagResource.GroupMember.ScaleFrame>(dataContext)); } } break; case ModelAnimationTagResource.AnimationCompressionFormats.Type8: // Type 8 is basically a type 3 but with rotation frames using 4 floats, or a realQuaternion var Format8 = BlamCache.Deserializer.Deserialize <ModelAnimationTagResource.GroupMember.Format8>(dataContext); CacheContext.Serializer.Serialize(dataContext, Format8); for (int nodeIndex = 0; nodeIndex < codec.RotationNodeCount; nodeIndex++) { for (int frameIndex = 0; frameIndex < member.FrameCount; frameIndex++) { CacheContext.Serializer.Serialize(dataContext, BlamCache.Deserializer.Deserialize <ModelAnimationTagResource.GroupMember.RotationFrameFloat>(dataContext)); } } blamResourceStream.Position = (long)member.AnimationData.Address.Offset + member.OverlayOffset + Format8.PositionFramesOffset; dataStream.Position = blamResourceStream.Position; for (int nodeIndex = 0; nodeIndex < codec.PositionNodeCount; nodeIndex++) { for (int frameIndex = 0; frameIndex < member.FrameCount; frameIndex++) { CacheContext.Serializer.Serialize(dataContext, BlamCache.Deserializer.Deserialize <ModelAnimationTagResource.GroupMember.PositionFrame>(dataContext)); } } blamResourceStream.Position = (long)member.AnimationData.Address.Offset + member.OverlayOffset + Format8.ScaleFramesOffset; dataStream.Position = blamResourceStream.Position; for (int nodeIndex = 0; nodeIndex < codec.ScaleNodeCount; nodeIndex++) { for (int frameIndex = 0; frameIndex < member.FrameCount; frameIndex++) { CacheContext.Serializer.Serialize(dataContext, BlamCache.Deserializer.Deserialize <ModelAnimationTagResource.GroupMember.ScaleFrame>(dataContext)); } } break; default: throw new DataMisalignedException(); } #region How Footer/Flags works // Better description by DemonicSandwich from http://remnantmods.com/forums/viewtopic.php?f=13&t=1574 : Node List Block: (matches my previous observations) // Just a block of flags. Tick a flag and the respective node will be affected by animation. // The size of this block should always be a multiple of 12. It's size is determined my the meta value Node List Size [byte, offset: 61] // When set to 12, the list can handle objects with a node count up to 32 (0-31). // When set to 24, the object can have 64 nodes and so on. // The block is split into 3 groups of flags. // The first group determines what nodes are affected by rotation, the second group for position, and the third group for scale. // // If looking at it in hex, the Node ticks for each group will be in order as follows: // [7][6][5][4][3][2][1][0] - [15][14][13][12][11][10][9][8] - etc. // Each flag corresponding to a Node index. #endregion #region Footer/Flag block // There's one bitfield32 for every 32 nodes that are animated which i'll call a node flags. // There's at least 3 flags if the animation only has an overlay header, which i'll call a flag set. // There's at least 6 flags if the animation has both a base header and an overlay header, so 2 sets. // If the animated nodes count is over 32, then a new flags set is added. // 1 set per header is added, such as 32 nodes = 1 set, 64 = 2 sets, 96 = 3 sets etc , 128-256 maybe max blamResourceStream.Position = (long)member.AnimationData.Address.Offset + member.OverlayOffset + member.FlagsOffset; dataStream.Position = blamResourceStream.Position; var footerSizeBase = (byte)member.BaseHeader / 4; for (int flagsCount = 0; flagsCount < footerSizeBase; flagsCount++) { CacheContext.Serializer.Serialize(dataContext, BlamCache.Deserializer.Deserialize <ModelAnimationTagResource.GroupMember.ScaleFrame>(dataContext)); } var footerSizeOverlay = (byte)member.OverlayHeader / 4; for (int flagsCount = 0; flagsCount < footerSizeOverlay; flagsCount++) { CacheContext.Serializer.Serialize(dataContext, BlamCache.Deserializer.Deserialize <ModelAnimationTagResource.GroupMember.ScaleFrame>(dataContext)); } #endregion switch (member.MovementDataType) { case ModelAnimationTagResource.GroupMemberMovementDataType.None: if (member.Unknown1 > 0) { for (int i = 0; i < member.FrameCount; i++) { CacheContext.Serializer.Serialize(dataContext, BlamCache.Deserializer.Deserialize <ModelAnimationTagResource.GroupMember.FrameInfoDyaw>(dataContext)); } } if (member.Unknown2 > 0) { for (int i = 0; i < member.FrameCount; i++) { CacheContext.Serializer.Serialize(dataContext, BlamCache.Deserializer.Deserialize <ModelAnimationTagResource.GroupMember.FrameInfoDxDyDyaw>(dataContext)); } } break; case ModelAnimationTagResource.GroupMemberMovementDataType.dx_dy: if (member.Unknown1 > 0) { for (int i = 0; i < member.FrameCount; i++) { CacheContext.Serializer.Serialize(dataContext, BlamCache.Deserializer.Deserialize <ModelAnimationTagResource.GroupMember.FrameInfoDxDy>(dataContext)); } } if (member.Unknown2 > 0) { for (int i = 0; i < member.FrameCount; i++) { CacheContext.Serializer.Serialize(dataContext, BlamCache.Deserializer.Deserialize <ModelAnimationTagResource.GroupMember.FrameInfoDxDyDyaw>(dataContext)); } } break; case ModelAnimationTagResource.GroupMemberMovementDataType.dx_dy_dyaw: if (member.Unknown1 > 0) { for (int i = 0; i < member.FrameCount; i++) { CacheContext.Serializer.Serialize(dataContext, BlamCache.Deserializer.Deserialize <ModelAnimationTagResource.GroupMember.FrameInfoDxDyDyaw>(dataContext)); } } if (member.Unknown2 > 0) { for (int i = 0; i < member.FrameCount; i++) { CacheContext.Serializer.Serialize(dataContext, BlamCache.Deserializer.Deserialize <ModelAnimationTagResource.GroupMember.FrameInfoDxDyDyaw>(dataContext)); } } break; case ModelAnimationTagResource.GroupMemberMovementDataType.dx_dy_dz_dyaw: if (member.Unknown1 > 0) { for (int i = 0; i < member.FrameCount; i++) { CacheContext.Serializer.Serialize(dataContext, BlamCache.Deserializer.Deserialize <ModelAnimationTagResource.GroupMember.FrameInfoDxDyDzDyaw>(dataContext)); } } if (member.Unknown2 > 0) { for (int i = 0; i < member.FrameCount; i++) { CacheContext.Serializer.Serialize(dataContext, BlamCache.Deserializer.Deserialize <ModelAnimationTagResource.GroupMember.FrameInfoDxDyDzDyaw>(dataContext)); } } break; default: break; } dataStream.Position = memberOffset + member.AnimationData.Size; // Before the next animation member, there's some padding that is garbage data in H3/ODST, but zeroed in HO. // In order to compare converted to original raw easily, copy the original data. while (blamResourceStream.Position % 0x10 != 0) // align to 0x10, useless padding of garbage data, it's zeroed in 1:1 HO raw, just read as 4 lame bytes { if (blamResourceStream.Position == blamResourceStream.Length) { break; } CacheContext.Serializer.Serialize(dataContext, BlamCache.Deserializer.Deserialize <ModelAnimationTagResource.GroupMember.ScaleFrame>(dataContext)); } // Align the next animation member to 0x10. memberOffset += member.AnimationData.Size; while (memberOffset % 0x10 != 0) { memberOffset += 4; } } dataStream.Position = 0; CacheContext.Serializer.Serialize(new ResourceSerializationContext(CacheContext, group.Resource), resourceDefinition[resDefIndex]); group.Resource.ChangeLocation(ResourceLocation.ResourcesB); var resource = group.Resource; if (resource == null) { throw new ArgumentNullException("resource"); } if (!dataStream.CanRead) { throw new ArgumentException("The input stream is not open for reading", "dataStream"); } var cache = CacheContext.GetResourceCache(ResourceLocation.ResourcesB); if (!resourceStreams.ContainsKey(ResourceLocation.ResourcesB)) { resourceStreams[ResourceLocation.ResourcesB] = FlagIsSet(PortingFlags.Memory) ? new MemoryStream() : (Stream)CacheContext.OpenResourceCacheReadWrite(ResourceLocation.ResourcesB); if (FlagIsSet(PortingFlags.Memory)) { using (var resourceStream = CacheContext.OpenResourceCacheRead(ResourceLocation.ResourcesB)) resourceStream.CopyTo(resourceStreams[ResourceLocation.ResourcesB]); } } var dataSize = (int)(dataStream.Length - dataStream.Position); var data = new byte[dataSize]; dataStream.Read(data, 0, dataSize); resource.Page.Index = cache.Add(resourceStreams[ResourceLocation.ResourcesB], data, out uint compressedSize); resource.Page.CompressedBlockSize = compressedSize; resource.Page.UncompressedBlockSize = (uint)dataSize; resource.DisableChecksum(); } } return(resourceGroups); }
public CachedTag FixRmt2Reference(Stream cacheStream, string blamTagName, CachedTag blamRmt2Tag, RenderMethodTemplate blamRmt2Definition, List <string> bmMaps, List <string> bmArgs) { switch (blamTagName) { case @"levels\multi\snowbound\shaders\cov_grey_icy": try { return(CacheContext.GetTag <RenderMethodTemplate>(@"ms30\shaders\shader_templates\_0_2_0_1_7_2_0_0_0_0_0_0")); } catch { } break; case @"objects\vehicles\ghost\shaders\ghost_damage": case @"objects\vehicles\wraith\shaders\wraith_blown_open": case @"objects\vehicles\banshee\shaders\banshee_damage": try { return(CacheContext.GetTag <RenderMethodTemplate>(@"shaders\shader_templates\_0_2_0_1_2_2_2_0_1_1_0")); } catch { } break; case @"objects\vehicles\ghost\shaders\ghost_torn": case @"objects\vehicles\banshee\shaders\banshee_torn": case @"objects\vehicles\wraith\shaders\wraith_torn": try { return(CacheContext.GetTag <RenderMethodTemplate>(@"shaders\shader_templates\_0_2_1_1_2_2_0_0_0_0_0")); } catch { } break; case @"objects\vehicles\wraith\shaders\wraith_torn_metal": try { return(CacheContext.GetTag <RenderMethodTemplate>(@"shaders\shader_templates\_0_2_1_1_1_2_0_0_0_0_0")); } catch { } break; case @"objects\vehicles\ghost\shaders\ghost_dash_zcam": try { return(CacheContext.GetTag <RenderMethodTemplate>(@"shaders\halogram_templates\_0_11_0_1_0_2_0")); } catch { } break; case @"fx\particles\energy\electric_arcs_blue": try { return(CacheContext.GetTag <RenderMethodTemplate>(@"shaders\particle_templates\_2_8_0_0_0_0_1_0_0_0")); } catch { } break; case @"objects\weapons\melee\energy_blade\fx\particles\plasma_wispy": try { return(CacheContext.GetTag <RenderMethodTemplate>(@"shaders\particle_templates\_5_8_0_0_0_1_0_0_0_0")); } catch { } break; case @"objects\weapons\melee\energy_blade\fx\particles\energy_pulse": try { return(CacheContext.GetTag <RenderMethodTemplate>(@"shaders\particle_templates\_3_7_0_0_1_0_0_0_0_0")); } catch { } break; case @"levels\dlc\fortress\shaders\panel_platform_center": try { return(CacheContext.GetTag <RenderMethodTemplate>(@"shaders\shader_templates\_0_1_0_1_2_2_5_0_1_0_0")); } catch { } break; case @"levels\dlc\sidewinder\shaders\side_tree_branch_snow": try { return(CacheContext.GetTag <RenderMethodTemplate>(@"shaders\shader_templates\_0_1_1_0_0_2_5_0_0_0_0")); } catch { } break; case @"levels\dlc\sidewinder\shaders\justin\sw_ground_ice1": case @"levels\dlc\sidewinder\shaders\justin\sw_ground_rock1": try { return(CacheContext.GetTag <RenderMethodTemplate>(@"shaders\terrain_templates\_0_0_1_1_1_2")); } catch { } break; case @"levels\multi\snowbound\sky\shaders\skydome": try { return(CacheContext.GetTag <RenderMethodTemplate>(@"shaders\shader_templates\_0_0_0_0_0_0_0_0_0_0_0")); } catch { } break; case @"levels\solo\020_base\lights\light_volume_hatlight": try { return(CacheContext.GetTag <RenderMethodTemplate>(@"shaders\halogram_templates\_0_5_1_0_0_1_1")); } catch { } break; case @"levels\dlc\armory\shaders\metal_doodad_a": case @"levels\dlc\armory\shaders\metal_doodad_a_illum_blue": case @"levels\dlc\armory\shaders\metal_doodad_a_illum_cool": case @"levels\dlc\armory\shaders\metal_doodad_a_illum_red": try { return(CacheContext.GetTag <RenderMethodTemplate>(@"shaders\shader_templates\_7_2_0_1_1_0_1_0_0_0_0")); } catch { } break; case @"levels\dlc\armory\shaders\razor_wire": try { return(CacheContext.GetTag <RenderMethodTemplate>(@"shaders\shader_templates\_0_1_1_2_5_2_0_1_0_0_0")); } catch { } break; case @"levels\multi\deadlock\shaders\deadlock_concrete_wall_a_rubble": try { return(CacheContext.GetTag <RenderMethodTemplate>(@"shaders\shader_templates\_0_2_0_0_0_0_0_0_0_0_0")); } catch { } break; case @"levels\multi\snowbound\shaders\rock_cliffs": case @"levels\multi\snowbound\shaders\rock_rocky": case @"levels\multi\snowbound\shaders\rock_rocky_icy": case @"levels\solo\020_base\shaders\hb_metal_arch_unwrap_a": try { return(CacheContext.GetTag <RenderMethodTemplate>(@"shaders\shader_templates\_7_2_0_1_2_1_0_0_1_0_0")); } catch { } break; case @"levels\dlc\armory\shaders\concrete_wall_01": case @"levels\dlc\armory\shaders\concrete_wall_01_blue": case @"levels\dlc\armory\shaders\concrete_wall_01_red": case @"levels\dlc\armory\shaders\concrete_wall_02_blue": case @"levels\dlc\armory\shaders\concrete_wall_02_red": try { return(CacheContext.GetTag <RenderMethodTemplate>(@"shaders\shader_templates\_7_2_0_1_7_0_0_0_0_0_0")); } catch { } break; case @"objects\levels\solo\010_jungle\shaders\dam_fence": try { return(CacheContext.GetTag <RenderMethodTemplate>(@"shaders\shader_templates\_0_1_1_1_1_2_0_0_0_1_0")); } catch { } break; case @"levels\dlc\chillout\shaders\chillout_capsule_liquid": try { return(CacheContext.GetTag <RenderMethodTemplate>(@"shaders\halogram_templates\_2_5_1_0_1_2_1")); } catch { } break; case @"levels\dlc\chillout\shaders\chillout_flood_godrays": case @"levels\dlc\chillout\shaders\chillout_invis_godrays": try { return(CacheContext.GetTag <RenderMethodTemplate>(@"shaders\halogram_templates\_0_5_1_0_0_1_1")); } catch { } break; case @"objects\levels\dlc\chillout\shaders\chill_energy_blocker_small": case @"objects\levels\dlc\chillout\shaders\chill_viewing_area_blocker": try { return(CacheContext.GetTag <RenderMethodTemplate>(@"shaders\halogram_templates\_0_8_1_0_0_4_1")); } catch { } break; case @"levels\dlc\chillout\shaders\chillout_floodroom01": case @"levels\dlc\chillout\shaders\chillout_floodroom02": case @"levels\dlc\chillout\shaders\chillout_floodroom03": case @"levels\dlc\chillout\shaders\chillout_transporter": try { return(CacheContext.GetTag <RenderMethodTemplate>(@"shaders\shader_templates\_0_2_0_1_1_2_5_0_0_1_0")); } catch { } break; case @"levels\dlc\chillout\shaders\chillout_flood_suckers": try { return(CacheContext.GetTag <RenderMethodTemplate>(@"shaders\shader_templates\_0_1_1_2_1_1_0_0_0_0_0")); } catch { } break; case @"levels\shared\shaders\flood\flood_sackyb": try { return(CacheContext.GetTag <RenderMethodTemplate>(@"shaders\shader_templates\_0_1_0_0_1_0_0_3_1_1_0")); } catch { } break; case @"objects\characters\flood_infection\shaders\flood_fronds": case @"objects\characters\flood_tank\shaders\flood_fronds": try { return(CacheContext.GetTag <RenderMethodTemplate>(@"shaders\shader_templates\_0_1_1_0_0_2_5_0_0_0_0")); } catch { } break; case @"objects\characters\flood_infection\shaders\flood_infection": try { return(CacheContext.GetTag <RenderMethodTemplate>(@"ms30\shaders\shader_templates\_0_2_0_1_1_0_1_0_0_0_0_0")); } catch { } break; case @"objects\weapons\melee\energy_blade\shaders\energy_blade": try { return(CacheContext.GetTag <RenderMethodTemplate>(@"shaders\shader_templates\_0_2_0_1_1_0_3_3_1_1_0")); } catch { } break; case @"objects\weapons\rifle\plasma_rifle_red\shaders\plasma_rifle_red": case @"objects\weapons\rifle\plasma_rifle\shaders\plasma_rifle": case @"objects\weapons\rifle\covenant_carbine\shaders\carbine": case @"objects\weapons\rifle\covenant_carbine\shaders\carbine_dull": case @"objects\weapons\pistol\plasma_pistol\shaders\plasma_pistol_metal": case @"objects\weapons\pistol\needler\shaders\needler_blue": case @"objects\weapons\pistol\needler\shaders\needler_pink": case @"objects\weapons\support_high\flak_cannon\shaders\flak_cannon": case @"objects\weapons\rifle\beam_rifle\shaders\beam_rifle": case @"objects\weapons\rifle\beam_rifle\shaders\beam_rifle2": try { return(CacheContext.GetTag <RenderMethodTemplate>(@"shaders\shader_templates\_0_2_0_1_2_1_1_0_0_0_0")); } catch { } break; case @"objects\weapons\pistol\needler\shaders\needler_glass": try { return(CacheContext.GetTag <RenderMethodTemplate>(@"shaders\shader_templates\_0_0_0_0_0_1_0_3_0_0_0")); } catch { } break; case @"objects\weapons\rifle\sniper_rifle\shaders\scope_alpha": try { return(CacheContext.GetTag <RenderMethodTemplate>(@"shaders\halogram_templates\_0_11_0_1_0_2_0")); } catch { } break; //Vehicles case @"objects\vehicles\scorpion\turrets\cannon\shaders\turret_cannon": try { return(CacheContext.GetTag <RenderMethodTemplate>(@"shaders\shader_templates\_3_2_0_1_1_0_0_0_0_0_0")); } catch { } break; } // Find existing rmt2 tags // If tagnames are not fixed, ms30 tags have an additional _0 or _0_0. This shouldn't happen if the tags have proper names, so it's mostly to preserve compatibility with older tagnames using (var reader = new EndianReader(cacheStream, true)) { foreach (var instance in CacheContext.TagCache.TagTable) { if (instance == null || !instance.IsInGroup("rmt2") || instance.Name == null) { continue; } var rmt2Name = instance.Name; // ignore s3d rmt2s if (rmt2Name.StartsWith("s3d")) { continue; } // check if rmt2 is from ms30 if (rmt2Name.StartsWith("ms30")) { rmt2Name = rmt2Name.Replace("ms30\\", ""); // skip over ms30 rmt2s if (!UseMS30) { continue; } } //match found if (rmt2Name.StartsWith(blamRmt2Tag.Name)) { return(instance); } } } // if no tagname matches, find rmt2 tags based on the most common values in the name return(FindEquivalentRmt2(cacheStream, blamRmt2Tag, blamRmt2Definition, bmMaps, bmArgs)); }
private void btnImport_Click(object sender, RoutedEventArgs e) { var ofd = new OpenFileDialog { Title = "Open Tag Container", Filter = "Tag Container Files|*.tagc" }; bool? result = ofd.ShowDialog(); if (!result.Value) return; TagContainer container; using (var reader = new EndianReader(File.OpenRead(ofd.FileName), Endian.BigEndian)) container = TagContainerReader.ReadTagContainer(reader); var injector = new TagContainerInjector(_cacheFile, container); using (IStream stream = _mapManager.OpenReadWrite()) { foreach (ExtractedTag tag in container.Tags) injector.InjectTag(tag, stream); injector.SaveChanges(stream); } // Fix the SID trie foreach (StringID sid in injector.InjectedStringIDs) _stringIdTrie.Add(_cacheFile.StringIDs.GetString(sid)); LoadTags(); MetroMessageBox.Show("Import Successful", "Imported " + injector.InjectedTags.Count + " tag(s), " + injector.InjectedBlocks.Count + " data block(s), " + injector.InjectedPages.Count + " resource page pointer(s), " + injector.InjectedResources.Count + " resource pointer(s), and " + injector.InjectedStringIDs.Count + " stringID(s).\r\n\r\nPlease remember that you cannot poke to injected or modified tags without causing problems. Load the modified map in the game first.\r\n\r\nAdditionally, if applicable, make sure that your game executable is patched so that any map header hash checks are bypassed. Using an executable which only has RSA checks patched out will refuse to load the map."); }
internal override void DeserializeStreamer(EndianReader reader) { InitialFrameID = reader.ReadUInt32LE(); ((ISerializable)RequestedFormat).Deserialize(reader); }
static void Main(string[] args) { if (args.Length != 3) { Console.WriteLine("Usage: BlockAlignmentScanner <map dir> <in plugin dir> <out plugin dir>"); return; } var mapDir = args[0]; var inDir = args[1]; var outDir = args[2]; Console.WriteLine("Loading plugins..."); var pluginsByClass = new Dictionary<string, XDocument>(); foreach (var pluginPath in Directory.EnumerateFiles(inDir, "*.xml")) { Console.WriteLine("- {0}", pluginPath); var document = XDocument.Load(pluginPath); var className = Path.GetFileNameWithoutExtension(pluginPath); pluginsByClass[className] = document; } Console.WriteLine("Loading engine database..."); var exeDir = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location); var dbPath = Path.Combine(exeDir, "Formats", "Engines.xml"); var db = XMLEngineDatabaseLoader.LoadDatabase(dbPath); Console.WriteLine("Processing maps..."); var alignsByElem = new Dictionary<XElement, int>(); foreach (var mapPath in Directory.EnumerateFiles(mapDir, "*.map")) { Console.WriteLine("- {0}", Path.GetFileName(mapPath)); using (var reader = new EndianReader(File.OpenRead(mapPath), Endian.BigEndian)) { var map = CacheFileLoader.LoadCacheFile(reader, db); var visitedTagBlocks = new HashSet<uint>(); foreach (var tag in map.Tags) { if (tag == null || tag.Class == null || tag.MetaLocation == null) continue; // Get the plugin for the tag var className = CharConstant.ToString(tag.Class.Magic); XDocument plugin; if (!pluginsByClass.TryGetValue(className, out plugin)) continue; // Process it var baseOffset = tag.MetaLocation.AsOffset(); var baseElement = plugin.Element("plugin"); DetectAlignment(map, reader, baseOffset, baseElement, alignsByElem, visitedTagBlocks); } } } Console.WriteLine("Adjusting plugins..."); foreach (var align in alignsByElem) { if (align.Value != 4) { Console.WriteLine("- \"{0}\" -> align 0x{1:X}", align.Key.Attribute("name").Value, align.Value); align.Key.SetAttributeValue(XName.Get("align"), "0x" + align.Value.ToString("X")); } } if (!Directory.Exists(outDir)) Directory.CreateDirectory(outDir); Console.WriteLine("Saving plugins..."); foreach (var plugin in pluginsByClass) { var outPath = Path.Combine(outDir, plugin.Key + ".xml"); Console.WriteLine("- {0}", outPath); var settings = new XmlWriterSettings(); settings.Indent = true; settings.IndentChars = "\t"; using (var writer = XmlWriter.Create(outPath, settings)) plugin.Value.Save(writer); } }
public void Read(EndianReader stream) { DecompressedSize = stream.ReadUInt32(); CompressedSize = stream.ReadUInt32(); Flags = (BundleFlag)stream.ReadUInt16(); }
public override byte[] GetRawFromID(int ID, int DataLength) { EndianReader er; string fName = ""; var Entry = zone.RawEntries[ID & ushort.MaxValue]; if (Entry.SegmentIndex == -1) throw new InvalidDataException("Raw data not found."); var Loc = play.Segments[Entry.SegmentIndex]; //if (Loc.SoundRawIndex != -1) // return GetSoundRaw(ID); int index = (Loc.OptionalPageIndex2 != -1) ? Loc.OptionalPageIndex2 : (Loc.OptionalPageIndex != -1) ? Loc.OptionalPageIndex : Loc.RequiredPageIndex; int locOffset = (Loc.OptionalPageOffset2 != -1) ? Loc.OptionalPageOffset2 : (Loc.OptionalPageOffset != -1) ? Loc.OptionalPageOffset : Loc.RequiredPageOffset; if (index == -1 || locOffset == -1) throw new InvalidDataException("Raw data not found."); if (play.Pages[index].RawOffset == -1) { index = Loc.RequiredPageIndex; locOffset = Loc.RequiredPageOffset; } var Pool = play.Pages[index]; if (Pool.CacheIndex != -1) { fName = play.SharedCaches[Pool.CacheIndex].FileName; fName = fName.Substring(fName.LastIndexOf('\\')); fName = FilePath + fName; if (fName == Filename) er = Reader; else { FileStream fs = new FileStream(fName, FileMode.Open, FileAccess.Read); er = new EndianReader(fs, EndianFormat.BigEndian); } } else er = Reader; er.SeekTo(int.Parse(versionNode.ChildNodes[0].Attributes["rawTableOffset"].Value)); int offset = Pool.RawOffset + er.ReadInt32(); er.SeekTo(offset); byte[] compressed = er.ReadBytes(Pool.CompressedSize); byte[] decompressed = new byte[Pool.DecompressedSize]; if (Version >= DefinitionSet.Halo4Retail) { int decompressionContext = 0; XCompress.XMemCreateDecompressionContext(XCompress.XMemCodecType.LZX, 0, 0, ref decompressionContext); XCompress.XMemResetDecompressionContext(decompressionContext); XCompress.XMemDecompressStream(decompressionContext, decompressed, ref Pool.DecompressedSize, compressed, ref Pool.CompressedSize); XCompress.XMemDestroyDecompressionContext(decompressionContext); } else { BinaryReader BR = new BinaryReader(new DeflateStream(new MemoryStream(compressed), CompressionMode.Decompress)); decompressed = BR.ReadBytes(Pool.DecompressedSize); BR.Close(); BR.Dispose(); } byte[] data = new byte[(DataLength != -1) ? DataLength : (Pool.DecompressedSize - locOffset)]; int length = data.Length; if (length > decompressed.Length) length = decompressed.Length; Array.Copy(decompressed, locOffset, data, 0, length); if (er != Reader) { er.Close(); er.Dispose(); } return data; }
public InMemoryBlockCollection(IMetadataStream stream, EndianReader reader, XmlNode node, InMemoryBlockCollection parent, int parentBlockIndex) { this.stream = stream; defaultValues = new Dictionary <int, byte[]>(); XmlNode = node; ParentBlock = parent; ParentEntryIndex = parentBlockIndex; ChildBlocks = new List <InMemoryBlockCollection>(); ParentBlock?.ChildBlocks.Add(this); if (parent == null) //tag root { Name = stream.SourceTag.FileName(); blockRef = null; EntryCount = 1; EntrySize = node.GetIntAttribute("baseSize") ?? 0; data = reader.ReadBytes(VirtualSize); } else { offsetInParent = node.GetIntAttribute("offset") ?? 0; Name = node.GetStringAttribute("name"); blockRef = reader.ReadObject <TagBlock>(); EntryCount = BlockRef.IsInvalid ? 0 : BlockRef.Count; EntrySize = node.GetIntAttribute("elementSize", "entrySize", "size") ?? 0; if (EntryCount > 0) { reader.Seek(BlockRef.Pointer.Address, SeekOrigin.Begin); data = reader.ReadBytes(VirtualSize); } else { data = Array.Empty <byte>(); } } foreach (var element in node.SelectNodes("*[@offset][@defaultValue]").OfType <XmlNode>()) { var offset = element.GetIntAttribute("offset").Value; var defaultValue = element.GetStringAttribute("defaultValue"); Func <string, int> getFlagValue = (val) => val.Split('|').Select(s => 1 << int.Parse(s)).Sum(); byte[] bytes; switch (element.Name.ToLower()) { case "int8": case "enum8": case "blockindex8": bytes = new[] { defaultValue == "-1" ? byte.MaxValue : byte.Parse(defaultValue) }; break; case "int16": case "blockindex16": bytes = BitConverter.GetBytes(short.Parse(defaultValue)); break; case "uint16": case "enum16": bytes = BitConverter.GetBytes(ushort.Parse(defaultValue)); break; case "int32": case "blockindex32": bytes = BitConverter.GetBytes(int.Parse(defaultValue)); break; case "uint32": case "enum32": bytes = BitConverter.GetBytes(uint.Parse(defaultValue)); break; case "float32": bytes = BitConverter.GetBytes(float.Parse(defaultValue)); break; case "flags8": bytes = BitConverter.GetBytes((byte)getFlagValue(defaultValue)); break; case "flags16": bytes = BitConverter.GetBytes((ushort)getFlagValue(defaultValue)); break; case "flags32": bytes = BitConverter.GetBytes((uint)getFlagValue(defaultValue)); break; default: continue; } if (stream.ByteOrder == ByteOrder.BigEndian) { Array.Reverse(bytes); } defaultValues.Add(offset, bytes); } }
// Patch Creation private void btnCreatePatch_Click(object sender, RoutedEventArgs e) { try { // Check the user isn't completly retarded if (!CheckAllCreateMandatoryFields()) return; // Check the user isn't a skid if (!CheckAllCreateMetaFilesExists()) return; // Paths string cleanMapPath = txtCreatePatchUnModifiedMap.Text; string moddedMapPath = txtCreatePatchModifiedMap.Text; string outputPath = txtCreatePatchOutputPatch.Text; string previewImage = txtCreatePatchPreviewImage.Text; // Details string author = txtCreatePatchContentAuthor.Text; string desc = txtCreatePatchContentDescription.Text; string name = txtCreatePatchContentName.Text; string outputName = txtCreatePatchOutputName.Text; // Make dat patch var patch = new Patch { Author = author, Description = desc, Name = name, OutputName = outputName, Screenshot = String.IsNullOrEmpty(previewImage) ? null : File.ReadAllBytes(previewImage) }; EndianReader originalReader = null; EndianReader newReader = null; try { originalReader = new EndianReader(File.OpenRead(cleanMapPath), Endian.BigEndian); newReader = new EndianReader(File.OpenRead(moddedMapPath), Endian.BigEndian); ICacheFile originalFile = CacheFileLoader.LoadCacheFile(originalReader, App.AssemblyStorage.AssemblySettings.DefaultDatabase); ICacheFile newFile = CacheFileLoader.LoadCacheFile(newReader, App.AssemblyStorage.AssemblySettings.DefaultDatabase); if (cbCreatePatchHasCustomMeta.IsChecked != null && (bool) cbCreatePatchHasCustomMeta.IsChecked && cboxCreatePatchTargetGame.SelectedIndex < 4) { var targetGame = (TargetGame) cboxCreatePatchTargetGame.SelectedIndex; byte[] mapInfo = File.ReadAllBytes(txtCreatePatchMapInfo.Text); var mapInfoFileInfo = new FileInfo(txtCreatePatchMapInfo.Text); FileInfo blfFileInfo; patch.CustomBlfContent = new BlfContent(mapInfoFileInfo.FullName, mapInfo, targetGame); #region Blf Data if (PatchCreationBlfOption0.Visibility == Visibility.Visible) { blfFileInfo = new FileInfo(txtCreatePatchblf0.Text); patch.CustomBlfContent.BlfContainerEntries.Add(new BlfContainerEntry(blfFileInfo.Name, File.ReadAllBytes(blfFileInfo.FullName))); } if (PatchCreationBlfOption1.Visibility == Visibility.Visible) { blfFileInfo = new FileInfo(txtCreatePatchblf1.Text); patch.CustomBlfContent.BlfContainerEntries.Add(new BlfContainerEntry(blfFileInfo.Name, File.ReadAllBytes(blfFileInfo.FullName))); } if (PatchCreationBlfOption2.Visibility == Visibility.Visible) { blfFileInfo = new FileInfo(txtCreatePatchblf2.Text); patch.CustomBlfContent.BlfContainerEntries.Add(new BlfContainerEntry(blfFileInfo.Name, File.ReadAllBytes(blfFileInfo.FullName))); } if (PatchCreationBlfOption3.Visibility == Visibility.Visible) { blfFileInfo = new FileInfo(txtCreatePatchblf3.Text); patch.CustomBlfContent.BlfContainerEntries.Add(new BlfContainerEntry(blfFileInfo.Name, File.ReadAllBytes(blfFileInfo.FullName))); } #endregion } PatchBuilder.BuildPatch(originalFile, originalReader, newFile, newReader, patch); } finally { if (originalReader != null) originalReader.Close(); if (newReader != null) newReader.Close(); } IWriter output = new EndianWriter(File.Open(outputPath, FileMode.Create, FileAccess.Write), Endian.BigEndian); AssemblyPatchWriter.WritePatch(patch, output); output.Close(); MetroMessageBox.Show("Patch Created!", "Your patch has been created in the designated location. Happy sailing, modder!"); } catch (Exception ex) { MetroException.Show(ex); } }
public abstract bool Read(EndianReader reader);
private void LoadPatchToPoke() { try { using (var reader = new EndianReader(File.OpenRead(txtPokePatchFile.Text), Endian.LittleEndian)) { string magic = reader.ReadAscii(4); reader.SeekTo(0); if (magic == "asmp") { // Load into UI reader.Endianness = Endian.BigEndian; currentPatchToPoke = AssemblyPatchLoader.LoadPatch(reader); txtPokePatchAuthor.Text = currentPatchToPoke.Author; txtPokePatchDesc.Text = currentPatchToPoke.Description; txtPokePatchName.Text = currentPatchToPoke.Name; txtPokePatchInternalName.Text = currentPatchToPoke.MapInternalName; //txtPokePatchMapID.Text = currentPatchToPoke.MapID.ToString(CultureInfo.InvariantCulture); // Set Visibility PokePatchControls.Visibility = Visibility.Visible; } else { MetroMessageBox.Show("You can't poke a patch from Alteration/Ascension. Convert it to a Assembly Patch first"); return; } } // Set Screenshot if (currentPatchToPoke.Screenshot == null) { // Set default var source = new Uri(@"/Assembly;component/Metro/Images/super_patcher.png", UriKind.Relative); imgPokePreview.Source = new BitmapImage(source); } else { var image = new BitmapImage(); image.BeginInit(); image.StreamSource = new MemoryStream(currentPatchToPoke.Screenshot); image.EndInit(); imgPokePreview.Source = image; } } catch (Exception ex) { MetroException.Show(ex); } }
public void Versions01(ByteOrder order, bool dynamicRead) { var rng = new Random(); using (var stream = new MemoryStream()) using (var reader = new EndianReader(stream, order)) using (var writer = new EndianWriter(stream, order)) { reader.DynamicReadEnabled = dynamicRead; var rand = new object[6]; rand[0] = rng.Next(int.MinValue, int.MaxValue); writer.Write((int)rand[0]); writer.Write(1); rand[1] = (float)rng.NextDouble(); writer.Write((float)rand[1]); rand[2] = (float)rng.NextDouble(); writer.Write((float)rand[2]); rand[3] = (float)rng.NextDouble(); writer.Write((float)rand[3]); rand[4] = rng.NextDouble(); writer.Write((double)rand[4]); rand[5] = rng.NextDouble(); writer.Write((double)rand[5]); stream.Position = 0; var obj = (DataClass09)reader.ReadObject(typeof(DataClass09)); Assert.AreEqual(rand[0], obj.Property1); Assert.AreEqual(1, obj.Version); Assert.AreEqual(rand[1], obj.Property2); Assert.IsNull(obj.Property3); Assert.IsNull(obj.Property4); stream.Position = 4; writer.Write(2); stream.Position = 0; obj = (DataClass09)reader.ReadObject(typeof(DataClass09)); Assert.AreEqual(rand[0], obj.Property1); Assert.AreEqual(2, obj.Version); Assert.AreEqual(rand[2], obj.Property2); Assert.AreEqual(rand[3], obj.Property3); Assert.IsNull(obj.Property4); stream.Position = 4; writer.Write(3); stream.Position = 0; obj = (DataClass09)reader.ReadObject(typeof(DataClass09)); Assert.AreEqual(rand[0], obj.Property1); Assert.AreEqual(3, obj.Version); Assert.AreEqual(rand[2], obj.Property2); Assert.AreEqual(rand[3], obj.Property3); Assert.IsNull(obj.Property4); stream.Position = 4; writer.Write(4); stream.Position = 0; obj = (DataClass09)reader.ReadObject(typeof(DataClass09)); Assert.AreEqual(rand[0], obj.Property1); Assert.AreEqual(4, obj.Version); Assert.AreEqual(rand[2], obj.Property2); Assert.IsNull(obj.Property3); Assert.AreEqual(rand[4], obj.Property4); Assert.AreEqual(rand[5], obj.Property5); } }