/// <summary> /// Write data to the mmiof.bmf file /// </summary> /// <param name="stream">Stream of the mmiof.bmf file.</param> private void WriteToStream(Stream stream) { EndianWriter writer = new EndianWriter(stream, Endian.BigEndian); // Write Save Header _saveHeader.WriteTo(writer); writer.SeekTo(0); // Write the object list _objectList.Update(writer); writer.SeekTo(0); // Resign the Save _saveHeader.Resign(writer, stream); }
private void ReadResourceBuffers(BlamCacheFile cacheFile, ref Resource resourceRef) { bool[] convertedVertexBuffers = new bool[100]; bool[] convertedIndexBuffers = new bool[100]; using (EndianWriter writer = new EndianWriter(new MemoryStream(resourceRef.Info), Endian.LittleEndian)) { foreach (ResourceFixup fixup in resourceRef.ResourceFixups) { BlamCacheAddress address = new BlamCacheAddress(fixup.Address); writer.SeekTo(fixup.Offset); writer.WriteUInt32(address.Value); } } byte[] primaryResource = ReadResourcePageData(cacheFile, resourceRef.Location.PrimaryPage); byte[] secondaryResource = ReadResourcePageData(cacheFile, resourceRef.Location.SecondaryPage); using (EndianReader definitionReader = new EndianReader(new MemoryStream(resourceRef.Info), Endian.LittleEndian)) using (EndianReader primaryReader = new EndianReader(new MemoryStream(primaryResource), Endian.LittleEndian)) using (EndianReader secondaryReader = new EndianReader(new MemoryStream(secondaryResource), Endian.LittleEndian)) { BlamCacheAddress cacheAddress = new BlamCacheAddress((uint)resourceRef.BaseDefinitionAddress); Logger.AssertMsg(cacheAddress.Type == BlamCacheAddressType.Definition, "INVALID CACHE ADDRESS"); definitionReader.SeekTo(cacheAddress.Offset); StructureLayout layout = cacheFile.GetLayout("render geometry api resource definition"); StructureValueCollection values = StructureReader.ReadStructure(definitionReader, layout); BlamCacheAddress uselessCrap3Address = new BlamCacheAddress((uint)values.GetInteger("address of useless crap3")); BlamCacheAddress uselessCrap4Address = new BlamCacheAddress((uint)values.GetInteger("address of useless crap4")); } }
public override void Update(EndianWriter writer) { base.Update(writer); writer.SeekTo(SourceOffset + AmmoOffset); writer.WriteInt16(_remainingAmmo); writer.Skip(2); writer.WriteInt16(_clipAmmo); }
public override void Update(EndianWriter writer) { base.Update(writer); // Grenades writer.SeekTo(SourceOffset + GrenadesOffset); writer.WriteSByte(_fragGrenades); writer.WriteSByte(_plasmaGrenades); writer.WriteSByte(_spikeGrenades); writer.WriteSByte(_firebombGrenades); }
/// <summary> /// Updates any changes made to the object data. /// </summary> /// <param name="reader"> /// The EndianWriter to write to. /// It should point to the same stream that was used to load the object data, as seeking will be done automatically. /// </param> public virtual void Update(EndianWriter writer) { // Strength info long chunkStartOffset = _entry.ObjectAddress + (long)TableOffset.ObjectPool; writer.SeekTo(chunkStartOffset + StrengthInfoOffset); _healthInfo.WriteTo(writer); // BSP Zone writer.SeekTo(chunkStartOffset + 0x18); writer.WriteUInt16(_zone); // Position1 writer.SeekTo(chunkStartOffset + PositionOffset1); writer.WriteFloat(_positionMain.X); writer.WriteFloat(_positionMain.Y); writer.WriteFloat(_positionMain.Z); // Calculate extra position vectors Vector3 position2 = Vector3.Add(_position2Delta, _positionMain); Vector3 position3 = Vector3.Add(_position3Delta, _positionMain); Vector3 position4 = Vector3.Add(_position4Delta, _positionMain); // Position2 writer.SeekTo(chunkStartOffset + PositionOffset2); writer.WriteFloat(position2.X); writer.WriteFloat(position2.Y); writer.WriteFloat(position2.Z); // Position3 writer.SeekTo(chunkStartOffset + PositionOffset3); writer.WriteFloat(position3.X); writer.WriteFloat(position3.Y); writer.WriteFloat(position3.Z); // Position4 writer.SeekTo(chunkStartOffset + PositionOffset4); writer.WriteFloat(position4.X); writer.WriteFloat(position4.Y); writer.WriteFloat(position4.Z); }
protected override void LoadResourceData(BlamCacheFile cacheFile, ref Resource resourceRef) { bool[] convertedVertexBuffers = new bool[100]; bool[] convertedIndexBuffers = new bool[100]; using (EndianWriter writer = new EndianWriter(new MemoryStream(resourceRef.Info), Endian.LittleEndian)) { foreach (ResourceFixup fixup in resourceRef.ResourceFixups) { BlamCacheAddress address = new BlamCacheAddress(fixup.Address); writer.SeekTo(fixup.Offset); writer.WriteUInt32(address.Value); } } byte[] primaryResource = ReadResourcePageData(cacheFile, resourceRef.Location.PrimaryPage); byte[] secondaryResource = ReadResourcePageData(cacheFile, resourceRef.Location.SecondaryPage); //The using keyword will automatically call IDisposable.Dispose at the end of scope //Automatically freeing up our resources and closing our file streams using (EndianReader definitionReader = new EndianReader(new MemoryStream(resourceRef.Info), Endian.LittleEndian)) using (EndianReader primaryReader = new EndianReader(new MemoryStream(primaryResource), Endian.LittleEndian)) using (EndianReader secondaryReader = new EndianReader(new MemoryStream(secondaryResource), Endian.LittleEndian)) { BlamCacheAddress cacheAddress = new BlamCacheAddress((uint)resourceRef.BaseDefinitionAddress); Logger.AssertMsg(cacheAddress.Type == BlamCacheAddressType.Definition, "INVALID CACHE ADDRESS"); definitionReader.SeekTo(cacheAddress.Offset); StructureLayout layout = cacheFile.GetLayout("render geometry api resource definition"); StructureValueCollection values = StructureReader.ReadStructure(definitionReader, layout); //Won't be useless eventually ulong numberOfUselessCrap3 = values.GetInteger("number of useless crap3"); ulong numberOfUselessCrap4 = values.GetInteger("number of useless crap4"); BlamCacheAddress uselessCrap3Address = new BlamCacheAddress((uint)values.GetInteger("address of useless crap3 table")); BlamCacheAddress uselessCrap4Address = new BlamCacheAddress((uint)values.GetInteger("address of useless crap4 table")); StructureLayout vertexBufferDefinitionLayout = new StructureLayout(); vertexBufferDefinitionLayout.AddBasicField("vertex count", StructureValueType.Int32, 0x0); vertexBufferDefinitionLayout.AddBasicField("vertex format", StructureValueType.Int16, 0x4); vertexBufferDefinitionLayout.AddBasicField("vertex byte size", StructureValueType.Int16, 0x6); vertexBufferDefinitionLayout.AddBasicField("vertex buffer size", StructureValueType.Int32, 0x8); vertexBufferDefinitionLayout.AddBasicField("vertex buffer address", StructureValueType.UInt32, 0x14); //Vertex buffer data should be aligned to 0x4 StructureLayout indexBufferDefinitionLayout = new StructureLayout(); indexBufferDefinitionLayout.AddBasicField("index format", StructureValueType.Int16, 0x0); //Vertex buffer definitions //All of the vertex buffer definitions exist in a table of D3DPointer container structs //Each D3DPointer contains the address of the contained type (this is the only value we care about) //For example D3DPointer<Float> the first value might be 0x20000000 which would be an address containing some float VertexBufferDefinitions = new BlamD3DPointer <VertexBufferDefinition> [numberOfUselessCrap3]; StructureLayout d3dStructureLayout = BlamD3DPointer <VertexBufferDefinition> .Layout(); for (int i = 0; i < (int)numberOfUselessCrap3; i++) { //Read each D3DPointer struct (Make a class for this too) long offset = (i * d3dStructureLayout.Size); long readAddr = uselessCrap3Address.Offset + offset; definitionReader.SeekTo(readAddr); StructureValueCollection d3dStructureValues = StructureReader.ReadStructure(definitionReader, d3dStructureLayout); //Grab the pointer to the contained value (in our case it will be a VertexBufferDefinition) BlamCacheAddress vertexBufferDefinitionAddress = new BlamCacheAddress((uint)d3dStructureValues.GetInteger("address")); Logger.AssertMsg(vertexBufferDefinitionAddress.Type == BlamCacheAddressType.Definition, "Invalid vertex buffer definition address!"); //Read our vertex buffer definition (Make a class for this) definitionReader.SeekTo(vertexBufferDefinitionAddress.Offset); StructureValueCollection vertexBufferDefinitionValues = StructureReader.ReadStructure(definitionReader, vertexBufferDefinitionLayout); //Grab our vertex buffer address BlamCacheAddress vertexBufferAddress = new BlamCacheAddress((uint)vertexBufferDefinitionValues.GetInteger("vertex buffer address")); EndianReader vertexBufferReader = null; //Determine where to read the vertex data from switch (vertexBufferAddress.Type) { case BlamCacheAddressType.Data: vertexBufferReader = primaryReader; break; case BlamCacheAddressType.SecondaryData: vertexBufferReader = secondaryReader; break; case BlamCacheAddressType.Definition: vertexBufferReader = definitionReader; break; } Logger.AssertMsg(vertexBufferReader != null, "INVALID VERTEX BUFFER ADDRESS"); //Need to make a class for this too, BUT the layout depends on what type of vertex it is... //See https://github.com/MadJayQ/MCCEditor/blob/master/Blamite/Formats/Reach/Reach_VertexBuffer.xml //This is for Reach but it's the best we got ATM... StructureLayout vertexBufferLayout = new StructureLayout(); vertexBufferLayout.AddBasicField("posX", StructureValueType.Float32, 0x0); vertexBufferLayout.AddBasicField("posY", StructureValueType.Float32, 0x4); vertexBufferLayout.AddBasicField("posZ", StructureValueType.Float32, 0x8); vertexBufferLayout.AddBasicField("posW", StructureValueType.Float32, 0x10); //Read our vertex data buffer block long vertexByteSize = (long)vertexBufferDefinitionValues.GetInteger("vertex byte size"); long vertexBufferTotalSize = (long)vertexBufferDefinitionValues.GetInteger("vertex buffer size"); long vertexCount = (long)vertexBufferDefinitionValues.GetInteger("vertex count"); Logger.AssertMsgFormat(vertexBufferTotalSize == (vertexByteSize * vertexCount), "Malformed vertex buffer, vertex byte size and vertex count do not add up to the total vertex buffer size! Total: {0}, Vertex Size: {1}, Vertex Count: {2}", vertexBufferTotalSize, vertexByteSize, vertexCount); vertexBufferReader.SeekTo(vertexBufferAddress.Offset); byte[] vertexBlock = vertexBufferReader.ReadBlock((int)vertexBufferDefinitionValues.GetInteger("vertex buffer size")); using (EndianReader vertexBufferStreamReader = new EndianReader(new MemoryStream(vertexBlock), Endian.LittleEndian)) { for (int vertexIdx = 0; vertexIdx < vertexCount; vertexIdx++) { long vertexBlockOffset = (vertexIdx * vertexByteSize); StructureValueCollection vertexValues = StructureReader.ReadStructure(vertexBufferStreamReader, vertexBufferLayout); } } } //Index buffer definitions for (int i = 0; i < (int)numberOfUselessCrap4; i++) { long offset = (i * 0xC); long readAddr = uselessCrap4Address.Offset + offset; definitionReader.SeekTo(readAddr); StructureValueCollection d3dStructureValues = StructureReader.ReadStructure(definitionReader, d3dStructureLayout); BlamCacheAddress indexBufferDefinitionAddress = new BlamCacheAddress((uint)d3dStructureValues.GetInteger("address")); Logger.AssertMsg(indexBufferDefinitionAddress.Type == BlamCacheAddressType.Definition, "Invalid index buffer definition address!"); definitionReader.SeekTo(indexBufferDefinitionAddress.Offset); StructureValueCollection indexBufferDefinitionValues = StructureReader.ReadStructure(definitionReader, indexBufferDefinitionLayout); } } }
private string ConvertToAudioFile(ICollection <byte> data, string path = null) { var tempFile = Path.GetTempFileName(); byte[] footer; var codec = _soundResourceGestalt.SoundPlatformCodecs[_sound.CodecIndex]; switch (codec.Channel) { case Channel.Mono: footer = _monoFooter; break; case Channel.Stereo: footer = _stereoFooter; break; default: throw new NotImplementedException(); } switch (_sound.Encoding) { case Encoding.XMA: using (var fileStream = new FileStream(tempFile, FileMode.OpenOrCreate)) { using (var writer = new EndianWriter(fileStream, Endian.BigEndian)) { // Generate an XMA header // ADAPTED FROM wwisexmabank - I DO NOT TAKE ANY CREDIT WHATSOEVER FOR THE FOLLOWING CODE. // See http://hcs64.com/vgm_ripping.html for more information // 'riff' chunk writer.WriteInt32(0x52494646); // 'RIFF' writer.Endianness = Endian.LittleEndian; writer.WriteInt32(data.Count + 0x34); writer.Endianness = Endian.BigEndian; writer.WriteInt32(0x57415645); // 'data' chunk writer.Endianness = Endian.BigEndian; writer.WriteInt32(0x64617461); // 'data' writer.Endianness = Endian.LittleEndian; writer.WriteInt32(data.Count); writer.WriteBlock(data.ToArray()); // footer writer.WriteBlock(footer); // size writer.SeekTo(0x04); writer.WriteInt32((Int32)writer.Length - 0x08); } } VariousFunctions.RunProgramSilently(@"A:\Xbox\Games\towav.exe", string.Format("\"{0}\"", Path.GetFileName(tempFile)), Path.GetDirectoryName(tempFile)); if (File.Exists(tempFile)) { File.Delete(tempFile); } tempFile = Path.ChangeExtension(tempFile, "wav"); if (path != null) { File.Move(tempFile, path); } return(path ?? tempFile); default: throw new NotImplementedException(); } }
private string ConvertToAudioFile(ICollection <byte> data, string path = null) { string towav = Path.Combine(VariousFunctions.GetApplicationLocation(), "helpers", "towav.exe"); if (!File.Exists(towav)) { MetroMessageBox.Show("Cannot Convert Sound", "Sounds cannot be converted because towav.exe is not present. Copy it to the \\helpers folder inside your Assembly installation."); return(null); } var tempFile = Path.GetTempFileName(); byte[] footer; var codec = _soundResourceTable.Codecs[_sound.CodecIndex]; switch ((SoundEncoding)codec.Encoding) { case SoundEncoding.Mono: footer = _monoFooter; break; case SoundEncoding.Stereo: footer = _stereoFooter; break; default: throw new NotImplementedException(); } switch ((SoundCompression)codec.Compression) { case SoundCompression.XMA2: using (var fileStream = new FileStream(tempFile, FileMode.OpenOrCreate)) { using (var writer = new EndianWriter(fileStream, Endian.BigEndian)) { // Generate an XMA header // ADAPTED FROM wwisexmabank - I DO NOT TAKE ANY CREDIT WHATSOEVER FOR THE FOLLOWING CODE. // See http://hcs64.com/vgm_ripping.html for more information // 'riff' chunk writer.WriteInt32(0x52494646); // 'RIFF' writer.Endianness = Endian.LittleEndian; writer.WriteInt32(data.Count + 0x34); writer.Endianness = Endian.BigEndian; writer.WriteInt32(0x57415645); // 'data' chunk writer.Endianness = Endian.BigEndian; writer.WriteInt32(0x64617461); // 'data' writer.Endianness = Endian.LittleEndian; writer.WriteInt32(data.Count); writer.WriteBlock(data.ToArray()); // footer writer.WriteBlock(footer); // size writer.SeekTo(0x04); writer.WriteInt32((Int32)writer.Length - 0x08); } } VariousFunctions.RunProgramSilently(towav, string.Format("\"{0}\"", Path.GetFileName(tempFile)), Path.GetDirectoryName(tempFile)); if (File.Exists(tempFile)) { File.Delete(tempFile); } tempFile = Path.ChangeExtension(tempFile, "wav"); if (path != null) { File.Move(tempFile, path); } return(path ?? tempFile); default: throw new NotImplementedException(); } }
private void BasicProjectileSwap(string command) { command = command.ToLowerInvariant(); var targetWeaponTag = _tagEntries.FirstOrDefault(t => t.TagClass == "weap" && t.TagAliasNames.Contains("assault rifle")); if (targetWeaponTag == null) return; var newProjectileTag = _tagEntries.FirstOrDefault(t => t.TagClass == "proj" && t.TagAliasNames.Contains(command)); if (newProjectileTag == null) return; const uint baseOffset = 0xbf126690 + 0x98; // Tag Block Address + Initial Projectile Offset Gain var writer = new EndianWriter(_xbdm.MemoryStream, Endian.BigEndian); writer.SeekTo(baseOffset); writer.WriteUInt32((UInt32) newProjectileTag.Tag.Class.Magic); writer.WriteBlock(new byte[] { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }); writer.WriteUInt32(newProjectileTag.Tag.Index.Value); }