예제 #1
0
        /// <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"));
                    }
        }
예제 #3
0
        public override void Update(EndianWriter writer)
        {
            base.Update(writer);

            writer.SeekTo(SourceOffset + AmmoOffset);
            writer.WriteInt16(_remainingAmmo);
            writer.Skip(2);
            writer.WriteInt16(_clipAmmo);
        }
예제 #4
0
        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);
        }
예제 #5
0
        /// <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);
                        }
                    }
        }
예제 #7
0
        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();
            }
        }
예제 #8
0
        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();
            }
        }
예제 #9
0
        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);
        }