protected internal virtual void PostProcess(VoidPtr mdlAddress, VoidPtr dataAddress, StringTable stringTable)
        {
            ResourceGroup *pGroup = (ResourceGroup *)dataAddress;
            ResourceEntry *rEntry = &pGroup->_first;
            int            index  = 1;

            (*rEntry++) = new ResourceEntry(0xFFFF, 0, 0, 0, 0);

            if (_name == "Bones")
            {
                foreach (MDL0EntryNode n in _children)
                {
                    PostProcessBone(mdlAddress, n, pGroup, ref index, stringTable);
                }
            }
            else
            {
                foreach (MDL0EntryNode n in _children)
                {
                    dataAddress = (VoidPtr)pGroup + (rEntry++)->_dataOffset;
                    ResourceEntry.Build(pGroup, index++, dataAddress, (BRESString *)stringTable[n.Name]);
                    n.PostProcess(mdlAddress, dataAddress, stringTable);
                }
            }
        }
Exemple #2
0
        protected internal override void PostProcess(VoidPtr bresAddress, VoidPtr dataAddress, int dataLength, StringTable stringTable)
        {
            base.PostProcess(bresAddress, dataAddress, dataLength, stringTable);

            VIS0v3 *header = (VIS0v3 *)dataAddress;

            if (_version == 4)
            {
                ((VIS0v4 *)dataAddress)->ResourceStringAddress = stringTable[Name] + 4;
            }
            else
            {
                header->ResourceStringAddress = stringTable[Name] + 4;
            }

            ResourceGroup *group = header->Group;

            group->_first = new ResourceEntry(0xFFFF, 0, 0, 0, 0);

            ResourceEntry *rEntry = group->First;

            int index = 1;

            foreach (VIS0EntryNode n in Children)
            {
                dataAddress = (VoidPtr)group + (rEntry++)->_dataOffset;
                ResourceEntry.Build(group, index++, dataAddress, (BRESString *)stringTable[n.Name]);
                n.PostProcess(dataAddress, stringTable);
            }
        }
Exemple #3
0
        public void PostProcess(VoidPtr userDataAddr, StringTable stringTable)
        {
            if (Count == 0 || userDataAddr == null)
            {
                return;
            }

            UserData *data = (UserData *)userDataAddr;

            ResourceGroup *pGroup = data->Group;
            ResourceEntry *pEntry = &pGroup->_first;
            int            count  = pGroup->_numEntries;

            (*pEntry++) = new ResourceEntry(0xFFFF, 0, 0, 0, 0);

            for (int i = 0; i < count; i++)
            {
                UserDataEntry *entry = (UserDataEntry *)((byte *)pGroup + (pEntry++)->_dataOffset);
                if (entry->Type == UserValueType.String && entry->_entryCount > 0)
                {
                    entry->_dataOffset = (int)((VoidPtr)(stringTable[this[i]._entries[0]] + 4) - (VoidPtr)entry);
                }
                ResourceEntry.Build(pGroup, i + 1, entry, (BRESString *)stringTable[this[i]._name]);
                entry->ResourceStringAddress = stringTable[this[i]._name] + 4;
            }
        }
Exemple #4
0
        //To do
        //protected override int OnCalculateSize(bool force)
        //{
        //    int size = CLR0.Size + 0x18 + (Children.Count * 0x10);
        //    foreach (PAT0EntryNode n in Children)
        //        size += n.CalculateSize(force);
        //    return size;
        //}

        protected internal override void PostProcess(VoidPtr bresAddress, VoidPtr dataAddress, int dataLength, StringTable stringTable)
        {
            base.PostProcess(bresAddress, dataAddress, dataLength, stringTable);

            PAT0 *header = (PAT0 *)dataAddress;

            header->ResourceStringAddress = stringTable[Name] + 4;

            ResourceGroup *group = header->Group;

            group->_first = new ResourceEntry(0xFFFF, 0, 0, 0, 0);
            ResourceEntry *rEntry = group->First;

            int index = 1;

            foreach (PAT0EntryNode n in Children)
            {
                dataAddress = (VoidPtr)group + (rEntry++)->_dataOffset;
                ResourceEntry.Build(group, index++, dataAddress, (BRESString *)stringTable[n.Name]);
                n.PostProcess(dataAddress, stringTable);
            }

            bint *strings = header->StringOffsets1;

            for (int i = 0; i < _stringList1.Count; i++)
            {
                strings[i] = (int)stringTable[_stringList1[i]] + 4 - (int)strings;
            }

            strings = header->StringOffsets2;
            for (int i = 0; i < _stringList2.Count; i++)
            {
                strings[i] = (int)stringTable[_stringList2[i]] + 4 - (int)strings;
            }
        }
Exemple #5
0
        protected internal override void PostProcess(VoidPtr bresAddress, VoidPtr dataAddress, int dataLength, StringTable stringTable)
        {
            base.PostProcess(bresAddress, dataAddress, dataLength, stringTable);

            SHP0v3 *header = (SHP0v3 *)dataAddress;

            header->ResourceStringAddress = stringTable[Name] + 4;

            bint *stringPtr = header->StringEntries;

            for (int i = 0; i < header->_numEntries; i++)
            {
                stringPtr[i] = ((int)stringTable[_strings[i]] + 4) - (int)stringPtr;
            }

            ResourceGroup *group = header->Group;

            group->_first = new ResourceEntry(0xFFFF, 0, 0, 0, 0);

            ResourceEntry *rEntry = group->First;

            int index = 1;

            foreach (SHP0EntryNode n in Children)
            {
                dataAddress = (VoidPtr)group + (rEntry++)->_dataOffset;
                ResourceEntry.Build(group, index++, dataAddress, (BRESString *)stringTable[n.Name]);
                n.PostProcess(dataAddress, stringTable);
            }
        }
        protected internal virtual void PostProcess(VoidPtr mdlAddress, VoidPtr dataAddress, StringTable stringTable)
        {
            if (dataAddress <= mdlAddress)
            {
                return;
            }

            ResourceGroup *pGroup = (ResourceGroup *)dataAddress;
            ResourceEntry *rEntry = &pGroup->_first;
            int            index  = 1;

            (*rEntry++) = new ResourceEntry(0xFFFF, 0, 0, 0, 0);

            if (_name == "Definitions")
            {
                return;
            }

            List <ResourceNode> entries = _name == "Bones" ?
                                          ((MDL0Node)Parent)._linker.BoneCache.Select(x => x as ResourceNode).ToList() :
                                          Children;

            foreach (MDL0EntryNode n in entries)
            {
                dataAddress = (VoidPtr)pGroup + (rEntry++)->_dataOffset;
                ResourceEntry.Build(pGroup, index++, dataAddress, (BRESString *)stringTable[n.Name]);

                if (dataAddress > mdlAddress)
                {
                    n.PostProcess(mdlAddress, dataAddress, stringTable);
                }
            }
        }
Exemple #7
0
        protected internal override void PostProcess(VoidPtr bresAddress, VoidPtr dataAddress, int dataLength, StringTable stringTable)
        {
            base.PostProcess(bresAddress, dataAddress, dataLength, stringTable);

            SCN0v4 *header = (SCN0v4 *)dataAddress;

            header->ResourceStringAddress = stringTable[Name] + 4;

            ResourceGroup *group = header->Group;

            group->_first = new ResourceEntry(0xFFFF, 0, 0, 0, 0);

            ResourceEntry *rEntry = group->First;

            int index = 1;

            int[] indices = new int[] { -1, -1, -1, -1, -1 };
            foreach (SCN0GroupNode g in Children)
            {
                if (g._name == "LightSet(NW4R)")
                {
                    indices[0] = g.Index;
                }
                else if (g._name == "AmbLights(NW4R)")
                {
                    indices[1] = g.Index;
                }
                else if (g._name == "Lights(NW4R)")
                {
                    indices[2] = g.Index;
                }
                else if (g._name == "Fogs(NW4R)")
                {
                    indices[3] = g.Index;
                }
                else if (g._name == "Cameras(NW4R)")
                {
                    indices[4] = g.Index;
                }
            }

            for (int i = 0; i < 5; i++)
            {
                SCN0GroupNode n = indices[i] >= 0 ? Children[indices[i]] as SCN0GroupNode : null;
                if (n != null)
                {
                    dataAddress = (VoidPtr)group + (rEntry++)->_dataOffset;
                    ResourceEntry.Build(group, index++, dataAddress, (BRESString *)stringTable[n.Name]);
                    n.PostProcess(header, dataAddress, stringTable);
                }
            }

            if (_version == 5)
            {
                _userEntries.PostProcess(((SCN0v5 *)dataAddress)->UserData, stringTable);
            }
        }
Exemple #8
0
        protected internal override void PostProcess(VoidPtr bresAddress, VoidPtr dataAddress, int dataLength, StringTable stringTable)
        {
            base.PostProcess(bresAddress, dataAddress, dataLength, stringTable);

            ResourceGroup *group;

            if (_version == 5)
            {
                SCN0v5 *header = (SCN0v5 *)dataAddress;
                header->ResourceStringAddress = stringTable[Name] + 4;
                if (!String.IsNullOrEmpty(_originalPath))
                {
                    header->OrigPathAddress = stringTable[_originalPath] + 4;
                }
                group = header->Group;
            }
            else
            {
                SCN0v4 *header = (SCN0v4 *)dataAddress;
                header->ResourceStringAddress = stringTable[Name] + 4;
                if (!String.IsNullOrEmpty(_originalPath))
                {
                    header->OrigPathAddress = stringTable[_originalPath] + 4;
                }
                group = header->Group;
            }

            group->_first = new ResourceEntry(0xFFFF, 0, 0, 0, 0);
            ResourceEntry *rEntry = group->First;

            int index = 1;

            int[] indices = new int[] { -1, -1, -1, -1, -1 };
            foreach (SCN0GroupNode g in Children)
            {
                indices[(int)g._type] = g.Index;
            }

            VoidPtr addr = dataAddress;

            for (int i = 0; i < 5; i++)
            {
                SCN0GroupNode n = indices[i] >= 0 ? Children[indices[i]] as SCN0GroupNode : null;
                if (n != null)
                {
                    addr = (VoidPtr)group + (rEntry++)->_dataOffset;
                    ResourceEntry.Build(group, index++, addr, (BRESString *)stringTable[n.Name]);
                    n.PostProcess(dataAddress, addr, stringTable);
                }
            }

            if (_version == 5)
            {
                _userEntries.PostProcess(((SCN0v5 *)addr)->UserData, stringTable);
            }
        }
Exemple #9
0
        protected internal virtual void PostProcess(VoidPtr mdlAddress, VoidPtr dataAddress, StringTable stringTable)
        {
            ResourceGroup *pGroup = (ResourceGroup *)dataAddress;
            ResourceEntry *rEntry = &pGroup->_first;
            int            index  = 1;

            (*rEntry++) = new ResourceEntry(0xFFFF, 0, 0, 0, 0);

            if (_name == "Bones")
            {
                foreach (MDL0EntryNode n in _children)
                {
                    PostProcessBone(mdlAddress, n, pGroup, ref index, stringTable);
                }
            }
            else if (_name == "Textures")
            {
                //ResourceGroup* dGroup = (ResourceGroup*)((byte*)pGroup + pGroup->_totalSize);
                bool hasDec = false;
                foreach (MDL0TextureNode n in _children)
                {
                    if (n._texRefs.Count > 0)
                    {
                        ResourceEntry.Build(pGroup, index++, (byte *)pGroup + (rEntry++)->_dataOffset, (BRESString *)stringTable[n._name]);
                    }
                    if (n._decRefs.Count > 0)
                    {
                        hasDec = true;
                    }
                }
                if (hasDec)
                {
                    pGroup      = (ResourceGroup *)((byte *)pGroup + pGroup->_totalSize);
                    rEntry      = &pGroup->_first;
                    (*rEntry++) = new ResourceEntry(0xFFFF, 0, 0, 0, 0);
                    index       = 1;
                    foreach (MDL0TextureNode n in _children)
                    {
                        if (n._decRefs.Count > 0)
                        {
                            ResourceEntry.Build(pGroup, index++, (byte *)pGroup + (rEntry++)->_dataOffset, (BRESString *)stringTable[n._name]);
                        }
                    }
                }
            }
            else
            {
                foreach (MDL0EntryNode n in _children)
                {
                    dataAddress = (VoidPtr)pGroup + (rEntry++)->_dataOffset;
                    ResourceEntry.Build(pGroup, index++, dataAddress, (BRESString *)stringTable[n.Name]);
                    n.PostProcess(mdlAddress, dataAddress, stringTable);
                }
            }
        }
        private void PostProcessBone(VoidPtr mdlAddress, MDL0EntryNode node, ResourceGroup *group, ref int index, StringTable stringTable)
        {
            VoidPtr dataAddress = (VoidPtr)group + (&group->_first)[index]._dataOffset;

            ResourceEntry.Build(group, index++, dataAddress, (BRESString *)stringTable[node.Name]);
            node.PostProcess(mdlAddress, dataAddress, stringTable);

            foreach (MDL0EntryNode n in node.Children)
            {
                PostProcessBone(mdlAddress, n, group, ref index, stringTable);
            }
        }
Exemple #11
0
        protected internal override void PostProcess(VoidPtr bresAddress, VoidPtr dataAddress, int dataLength, StringTable stringTable)
        {
            base.PostProcess(bresAddress, dataAddress, dataLength, stringTable);

            SHP0v3 *header = (SHP0v3 *)dataAddress;

            if (_version == 4)
            {
                ((SHP0v4 *)dataAddress)->ResourceStringAddress = stringTable[Name] + 4;
                if (!String.IsNullOrEmpty(_originalPath))
                {
                    ((SHP0v4 *)dataAddress)->OrigPathAddress = stringTable[_originalPath] + 4;
                }
            }
            else
            {
                header->ResourceStringAddress = stringTable[Name] + 4;
                if (!String.IsNullOrEmpty(_originalPath))
                {
                    header->OrigPathAddress = stringTable[_originalPath] + 4;
                }
            }

            bint *stringPtr = header->StringEntries;

            for (int i = 0; i < header->_numEntries; i++)
            {
                stringPtr[i] = ((int)stringTable[_strings[i]] + 4) - (int)stringPtr;
            }

            ResourceGroup *group = header->Group;

            group->_first = new ResourceEntry(0xFFFF, 0, 0, 0, 0);

            ResourceEntry *rEntry = group->First;

            int index = 1;

            foreach (SHP0EntryNode n in Children)
            {
                dataAddress = (VoidPtr)group + (rEntry++)->_dataOffset;
                ResourceEntry.Build(group, index++, dataAddress, (BRESString *)stringTable[n.Name]);
                n.PostProcess(dataAddress, stringTable);
            }

            if (_version == 4)
            {
                _userEntries.PostProcess(((SHP0v4 *)dataAddress)->UserData, stringTable);
            }
        }
Exemple #12
0
        protected internal override void PostProcess(VoidPtr bresAddress, VoidPtr dataAddress, int dataLength, StringTable stringTable)
        {
            base.PostProcess(bresAddress, dataAddress, dataLength, stringTable);

            PAT0v3 *header = (PAT0v3 *)dataAddress;

            if (_version == 4)
            {
                ((PAT0v4 *)dataAddress)->ResourceStringAddress = stringTable[Name] + 4;
            }
            else
            {
                header->ResourceStringAddress = stringTable[Name] + 4;
            }

            ResourceGroup *group = header->Group;

            group->_first = new ResourceEntry(0xFFFF, 0, 0, 0, 0);
            ResourceEntry *rEntry = group->First;

            int index = 1;

            foreach (PAT0EntryNode n in Children)
            {
                dataAddress = (VoidPtr)group + (rEntry++)->_dataOffset;
                ResourceEntry.Build(group, index++, dataAddress, (BRESString *)stringTable[n.Name]);
                n.PostProcess(dataAddress, stringTable);
            }

            int   i       = 0;
            bint *strings = header->TexFile;

            for (i = 0; i < _textureFiles.Count; i++)
            {
                if (!String.IsNullOrEmpty(_textureFiles[i]))
                {
                    strings[i] = (int)stringTable[_textureFiles[i]] + 4 - (int)strings;
                }
            }

            strings = header->PltFile;

            for (i = 0; i < _paletteFiles.Count; i++)
            {
                if (!String.IsNullOrEmpty(_paletteFiles[i]))
                {
                    strings[i] = (int)stringTable[_paletteFiles[i]] + 4 - (int)strings;
                }
            }
        }
        protected internal virtual void PostProcess(VoidPtr scn0Address, VoidPtr dataAddress, StringTable stringTable)
        {
            ResourceGroup *group = (ResourceGroup *)dataAddress;

            group->_first = new ResourceEntry(0xFFFF, 0, 0, 0, 0);

            ResourceEntry *rEntry = group->First;

            int index = 1;

            foreach (SCN0EntryNode n in UsedChildren)
            {
                dataAddress = (VoidPtr)group + (rEntry++)->_dataOffset;
                ResourceEntry.Build(group, index++, dataAddress, (BRESString *)stringTable[n.Name]);
                //n.PostProcess(scn0Address, dataAddress, stringTable);
            }

            int len = 0;

            switch (_type)
            {
            case GroupType.LightSet:
                len = SCN0LightSet.Size;
                break;

            case GroupType.AmbientLight:
                len = SCN0AmbientLight.Size;
                break;

            case GroupType.Light:
                len = SCN0Light.Size;
                break;

            case GroupType.Fog:
                len = SCN0Fog.Size;
                break;

            case GroupType.Camera:
                len = SCN0Camera.Size;
                break;
            }
            bint *  hdr     = (bint *)scn0Address + 5;
            VoidPtr entries = scn0Address + hdr[(int)_type];

            foreach (SCN0EntryNode n in Children)
            {
                n.PostProcess(scn0Address, entries, stringTable);
                entries += len;
            }
        }
Exemple #14
0
        public override void OnRebuild(VoidPtr address, int size, bool force)
        {
            BRESHeader *header = (BRESHeader *)address;

            *header = new BRESHeader(size, _numEntries + 1);

            ROOTHeader *rootHeader = header->First;

            *rootHeader = new ROOTHeader(_rootSize, Children.Count);

            ResourceGroup *pMaster = &rootHeader->_master;
            ResourceGroup *rGroup  = (ResourceGroup *)pMaster->EndAddress;

            //Write string table
            _stringTable.WriteTable(address + _strOffset);

            VoidPtr dataAddr = (VoidPtr)rootHeader + _rootSize;

            int gIndex = 1;

            foreach (BRESGroupNode g in Children)
            {
                ResourceEntry.Build(pMaster, gIndex++, rGroup, (BRESString *)_stringTable[g.Name]);

                *rGroup = new ResourceGroup(g.Children.Count);
                ResourceEntry *nEntry = rGroup->First;

                int rIndex = 1;
                foreach (BRESEntryNode n in g.Children)
                {
                    //Align data
                    dataAddr = ((int)dataAddr).Align(n.DataAlign);

                    ResourceEntry.Build(rGroup, rIndex++, dataAddr, (BRESString *)_stringTable[n.Name]);

                    //Rebuild entry
                    int len = n._calcSize;
                    n.Rebuild(dataAddr, len, force);
                    n.PostProcess(address, dataAddr, len, _stringTable);
                    dataAddr += len;
                }

                g._changed = false;

                //Advance to next group
                rGroup = (ResourceGroup *)rGroup->EndAddress;
            }

            _stringTable.Clear();
        }
Exemple #15
0
        protected internal virtual void PostProcess(VoidPtr dataAddress, StringTable stringTable)
        {
            ResourceGroup *group = (ResourceGroup *)dataAddress;

            group->_first = new ResourceEntry(0xFFFF, 0, 0, 0, 0);

            ResourceEntry *rEntry = group->First;

            int index = 1;

            foreach (SCN0EntryNode n in Children)
            {
                dataAddress = (VoidPtr)group + (rEntry++)->_dataOffset;
                ResourceEntry.Build(group, index++, dataAddress, (BRESString *)stringTable[n.Name]);
                n.PostProcess(dataAddress, stringTable);
            }
        }
        protected internal override void PostProcess(VoidPtr bresAddress, VoidPtr dataAddress, int dataLength, StringTable stringTable)
        {
            base.PostProcess(bresAddress, dataAddress, dataLength, stringTable);

            ResourceGroup *group;

            if (_version == 5)
            {
                CHR0v5 *header = (CHR0v5 *)dataAddress;
                header->ResourceStringAddress = (int)stringTable[Name] + 4;
                if (!String.IsNullOrEmpty(_originalPath))
                {
                    header->OrigPathAddress = stringTable[_originalPath] + 4;
                }
                group = header->Group;
            }
            else
            {
                CHR0v4_3 *header = (CHR0v4_3 *)dataAddress;
                header->ResourceStringAddress = (int)stringTable[Name] + 4;
                if (!String.IsNullOrEmpty(_originalPath))
                {
                    header->OrigPathAddress = stringTable[_originalPath] + 4;
                }
                group = header->Group;
            }

            group->_first = new ResourceEntry(0xFFFF, 0, 0, 0, 0);
            ResourceEntry *rEntry = group->First;

            int index = 1;

            foreach (CHR0EntryNode n in Children)
            {
                dataAddress = (VoidPtr)group + (rEntry++)->_dataOffset;
                ResourceEntry.Build(group, index++, dataAddress, (BRESString *)stringTable[n.Name]);
                n.PostProcess(dataAddress, stringTable);
            }

            if (_version == 5)
            {
                _userEntries.PostProcess(((CHR0v5 *)dataAddress)->UserData, stringTable);
            }
        }
        //protected override int OnCalculateSize(bool force)
        //{

        //}

        protected internal override void PostProcess(VoidPtr mdlAddress, VoidPtr dataAddress, StringTable stringTable)
        {
            MDL0Material *header = (MDL0Material *)dataAddress;

            header->_mdl0Offset   = (int)mdlAddress - (int)dataAddress;
            header->_stringOffset = (int)stringTable[Name] + 4 - (int)dataAddress;

            header->_flag1     = _numTextures;
            header->_numLayers = _numLayers;
            header->_flag3     = _flag3;
            header->_flag4     = _flag4;
            header->_flag5     = _flag5;
            header->_flag6     = _flag6;
            header->_flag7     = _flag7;
            header->_flag8     = _flag8;
            header->_type      = _type;

            MDL0Data7Part4 *part4 = header->Part4;

            if (part4 != null)
            {
                ResourceGroup *group = part4->Group;
                group->_first = new ResourceEntry(0xFFFF, 0, 0, 0, 0);
                ResourceEntry *rEntry = group->First;

                for (int i = 0, x = 1; i < group->_numEntries; i++)
                {
                    MDL0Data7Part4Entry *entry = (MDL0Data7Part4Entry *)((int)group + (rEntry++)->_dataOffset);
                    ResourceEntry.Build(group, x++, entry, (BRESString *)stringTable[_part4Entries[i]]);
                    entry->ResourceStringAddress = stringTable[_part4Entries[i]] + 4;
                }
            }

            MDL0MatLayer *part3 = header->Part3;

            foreach (MDL0MaterialRefNode n in Children)
            {
                n.PostProcess(mdlAddress, part3++, stringTable);
            }
        }
Exemple #18
0
        protected internal override void PostProcess(VoidPtr mdlAddress, VoidPtr dataAddress, StringTable stringTable)
        {
            MDL0Bone *header = (MDL0Bone *)dataAddress;

            header->_mdl0Offset   = (int)mdlAddress - (int)dataAddress;
            header->_stringOffset = (int)stringTable[Name] + 4 - (int)dataAddress;

            //Entry strings
            if (_entries.Count > 0)
            {
                ResourceGroup *pGroup = (ResourceGroup *)((byte *)header + header->_part2Offset + 4);
                ResourceEntry *pEntry = &pGroup->_first;
                int            count  = pGroup->_numEntries;
                (*pEntry++) = new ResourceEntry(0xFFFF, 0, 0, 0, 0);

                for (int i = 0; i < count; i++)
                {
                    Part2DataEntry *entry = (Part2DataEntry *)((byte *)pGroup + (pEntry++)->_dataOffset);
                    entry->_stringOffset = (int)stringTable[_entries[i]] + 4 - ((int)entry + (int)dataAddress);
                    ResourceEntry.Build(pGroup, i + 1, entry, (BRESString *)stringTable[_entries[i]]);
                }
            }
        }
Exemple #19
0
        //protected override int OnCalculateSize(bool force)
        //{
        //    int size = 0;
        //    //Definitions

        //    foreach (ResourceNode node in Children)
        //    {
        //        size += node.CalculateSize(force);
        //    }

        //    return size;
        //}

        protected internal override void PostProcess(VoidPtr bresAddress, VoidPtr dataAddress, int dataLength, StringTable stringTable)
        {
            base.PostProcess(bresAddress, dataAddress, dataLength, stringTable);

            MDL0Header *   header = (MDL0Header *)dataAddress;
            ResourceGroup *pGroup, sGroup;
            ResourceEntry *pEntry, sEntry;
            bint *         offsets = header->Offsets;
            int            index, sIndex;

            //Model name
            header->StringOffset = (int)((byte *)stringTable[Name] + 4 - (byte *)header);

            //Post-process groups, using linker lists
            List <MDLResourceType> gList = ModelLinker.IndexBank[_version];

            foreach (MDL0GroupNode node in Children)
            {
                MDLResourceType type = (MDLResourceType)Enum.Parse(typeof(MDLResourceType), node.Name);
                if (((index = gList.IndexOf(type)) >= 0) && (type != MDLResourceType.Shaders))
                {
                    node.PostProcess(dataAddress, dataAddress + offsets[index], stringTable);
                }
            }

            //Post-process definitions
            index          = gList.IndexOf(MDLResourceType.Defs);
            pGroup         = (ResourceGroup *)(dataAddress + offsets[index]);
            pGroup->_first = new ResourceEntry(0xFFFF, 0, 0, 0);
            pEntry         = &pGroup->_first + 1;
            index          = 1;
            if (_hasTree)
            {
                ResourceEntry.Build(pGroup, index++, (byte *)pGroup + (pEntry++)->_dataOffset, (BRESString *)stringTable["NodeTree"]);
            }
            if (_hasMix)
            {
                ResourceEntry.Build(pGroup, index++, (byte *)pGroup + (pEntry++)->_dataOffset, (BRESString *)stringTable["NodeMix"]);
            }
            if (_hasOpa)
            {
                ResourceEntry.Build(pGroup, index++, (byte *)pGroup + (pEntry++)->_dataOffset, (BRESString *)stringTable["DrawOpa"]);
            }
            if (_hasXlu)
            {
                ResourceEntry.Build(pGroup, index++, (byte *)pGroup + (pEntry++)->_dataOffset, (BRESString *)stringTable["DrawXlu"]);
            }

            //Link shader names using material list
            index  = offsets[gList.IndexOf(MDLResourceType.Materials)];
            sIndex = offsets[gList.IndexOf(MDLResourceType.Shaders)];
            if ((index > 0) && (sIndex > 0))
            {
                pGroup = (ResourceGroup *)(dataAddress + index);
                sGroup = (ResourceGroup *)(dataAddress + sIndex);
                pEntry = &pGroup->_first + 1;
                sEntry = &sGroup->_first + 1;

                sGroup->_first = new ResourceEntry(0xFFFF, 0, 0, 0);
                index          = pGroup->_numEntries;
                for (int i = 1; i <= index; i++)
                {
                    ResourceEntry.Build(sGroup, i, (byte *)sGroup + (sEntry++)->_dataOffset, (BRESString *)((byte *)pGroup + (pEntry++)->_stringOffset - 4));
                }
            }
        }