Exemple #1
0
        private static void MapLoadUnitTest()
        {
            string targetFile = Core.Util.VisualStudioProvider.TryGetSolutionDirectoryInfo().FullName + "\\" + TARGET_MAP_FILE;

            using (BlamCacheFile blamCacheFile = new BlamCacheFile(targetFile))
            {
                const int          VEHICLE_MODEL_OFFSET = 0x34;
                ICacheFile         cacheFile            = blamCacheFile.Get();
                IEnumerable <ITag> vehicleTags          = cacheFile.Tags.FindTagsByGroup("vehi");
                StructureLayout    layout = blamCacheFile.BuildInfo.Layouts.GetLayout("tag reference");
                foreach (ITag vehicleTag in vehicleTags)
                {
                    string name = cacheFile.FileNames.GetTagName(vehicleTag);

                    //This is where in the memory region that the map exists a structure for the meta data exists
                    long tagRefPointer = vehicleTag.MetaLocation.AsOffset() + VEHICLE_MODEL_OFFSET;
                    blamCacheFile.Reader.SeekTo(tagRefPointer);
                    StructureValueCollection collection = StructureReader.ReadStructure(blamCacheFile.Reader, layout); //Try to read it

                    //Extract fields
                    ulong      groupMagic = collection.GetInteger("tag group magic");
                    DatumIndex datumIndex = new DatumIndex(collection.GetInteger("datum index"));
                    //Is this a valid datum?
                    bool isValid = cacheFile.Tags.IsValidIndex(datumIndex);

                    ITag   vehicleModelTag  = cacheFile.Tags[datumIndex];
                    string vehicleModelName = cacheFile.FileNames.GetTagName(vehicleModelTag);
                    string group            = CharConstant.ToString(vehicleModelTag.Group.Magic);
                    if (!TARGET_MODEL.Equals(vehicleModelName))
                    {
                        continue;
                    }

                    tagRefPointer = vehicleModelTag.MetaLocation.AsOffset();
                    blamCacheFile.Reader.SeekTo(tagRefPointer);
                    collection = StructureReader.ReadStructure(blamCacheFile.Reader, layout);
                    groupMagic = collection.GetInteger("tag group magic");
                    datumIndex = new DatumIndex(collection.GetInteger("datum index"));

                    isValid = cacheFile.Tags.IsValidIndex(datumIndex);

                    ITag   vehicleRenderModelTag = cacheFile.Tags[datumIndex];
                    string renderModelTagName    = CharConstant.ToString(vehicleRenderModelTag.Group.Magic);

                    BlamRenderModel warthogModel = new BlamRenderModel(vehicleRenderModelTag, blamCacheFile);
                }
            }
            Logger.LogReport("MapLoadUnitTest: Success!");
        }
Exemple #2
0
        protected byte[] ReadResourcePageData(BlamCacheFile cacheFile, ResourcePage page)
        {
            BlamCacheFile cache         = cacheFile;
            string        cacheFilePath = "";
            bool          cleanup       = false;

            if (page.FilePath != null)
            {
                cacheFilePath = Core.Util.VisualStudioProvider.TryGetSolutionDirectoryInfo().FullName + "\\" + page.FilePath;
                cleanup       = true;
                cache         = new BlamCacheFile(cacheFilePath);
            }

            byte[] decompressed = new byte[page.UncompressedSize];
            cacheFile.Reader.SeekTo(page.Offset);

            byte[] compressed = cacheFile.Reader.ReadBlock(page.CompressedSize);

            if (page.CompressionMethod == ResourcePageCompression.None)
            {
                decompressed = compressed;
            }
            else if (page.CompressionMethod == ResourcePageCompression.Deflate)
            {
                using (DeflateStream stream = new DeflateStream(new MemoryStream(compressed), CompressionMode.Decompress))
                    stream.Read(decompressed, 0, BitConverter.ToInt32(BitConverter.GetBytes(page.UncompressedSize), 0));
            }


            if (cleanup)
            {
                cache.Dispose();
            }

            return(decompressed);
        }
        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);
                        }
                    }
        }
Exemple #4
0
 protected virtual void LoadResourceData(BlamCacheFile cacheFile, ref Resource resourceRef)
 {
 }