/// <summary>
        /// Figures out if the tag defined by <paramref name="tag_datum"/> is loaded in the tag index
        /// </summary>
        /// <param name="tag_datum">tag item defined in this cache's tag index</param>
        /// <returns><see cref="Blam.DatumIndex.Null"/> if not loaded</returns>
        public Blam.DatumIndex IsLoaded(Blam.CacheIndex.Item tag_datum)
        {
            if (tag_datum.IsEmpty)
            {
                return(Blam.DatumIndex.Null);
            }

            return(IsLoaded(References[tag_datum.ReferenceName], tag_datum.GroupTag));
        }
예제 #2
0
        public override int AddDependent(Blam.CacheIndex.Item tag, Blam.CacheIndex.Item dependent_tag)
        {
            int index = Add(dependent_tag);             // add and\or get the index of the child id entry

            tag_database_entry_reference_block eref;

            lookup[tag.Datum].ChildIds.Add(out eref);             // add a new entry reference

            return(eref.EntryReference.Value = index);
        }
예제 #3
0
        public override int AddDependent(Blam.CacheIndex.Item tag, Blam.CacheIndex.Item dependent_tag)
        {
            int index = Add(dependent_tag);             // add and\or get the index of the child id entry

            var tag_entry  = lookup[tag.Datum];
            var dtag_entry = lookup[dependent_tag.Datum];

            Halo1.Tags.tag_database_entry_reference_block eref;
            dtag_entry.ReferenceIds.Add(out eref);             // add a new entry reference to the dependent tag which points to this tag
            eref.EntryReference.Value = tag_entry.Flags.Value;

            tag_entry.ChildIds.Add(out eref);             // add a new entry reference to this tag which points to the dependent tag

            return(eref.EntryReference.Value = index);
        }
예제 #4
0
        /// <summary>
        /// Little hack for <see cref="CacheTagIndex"/>
        /// </summary>
        /// <param name="item"></param>
        /// <param name="cache"></param>
        /// <param name="ignore_group_hack">Hack used for Halo 2/3 where the sound definitions use different group tags</param>
        internal void Read(Blam.CacheIndex.Item item, Blam.CacheFile cache, bool ignore_group_hack)
        {
            Debug.Assert.If(InCache, "Tried to read a cache tag while we were NOT in a cache. {0}:{1}.{2}", engine, Name, tagGroup.Name);
            // HACK: for Halo 2/3 sound groups
            if (!ignore_group_hack && tagGroup.ID != item.GroupTag.ID)
            {
                Debug.Assert.If(false, "Tried to read a cache tag with a non-matching cache tag datum. {0}:{1} [{2} !{3}",
                                engine, Name, tagGroup.TagToString(), item.GroupTag.TagToString());
            }

            cache.InputStream.Seek(item.Offset);

            VersionCtorAttribute upgrade_parameters;
            bool needs_upgrading = false;

            if (cache.EngineVersion.SupportsTagVersioning())
            {
                if ((upgrade_parameters = tagDefinition.VersionForEngine(cache.EngineVersion)) != null)
                {
                    needs_upgrading = true;
                    // It is ASSUMED that the group tag won't ever be needed for version construction
                    tagDefinition = tagDefinition.NewInstance((tagDefinition as IStructureOwner).OwnerObject, upgrade_parameters.Major, upgrade_parameters.Minor);
                    flags.Add(IO.ITagStreamFlags.DefinitionWasUpgraded);
                }
                else
                {
                    needs_upgrading = false;
                }
            }

            tagDefinition.Read(cache);

            if (needs_upgrading)
#if DEBUG
            { if (!tagDefinition.Upgrade())
              {
                  Debug.Assert.If(false, "Failed to upgrade tag group. {0} {1}", tagDefinition.GetType().Name, tagDefinition.ToVersionString());
              }
            }
#else
            { tagDefinition.Upgrade(); }
#endif
        }
예제 #5
0
        public override int Add(Blam.CacheIndex.Item tag)
        {
            int index = -1;

            tag_database_entry_block entry;

            if (!lookup.TryGetValue(tag.Datum, out entry))             // hey, not in the database
            {
                index = db.Entries.Count;                              // count will be the index of our new entry
                db.Entries.Add(out entry);                             // add a new entry
                entry.Name.Value =                                     // set the name
                                   cacheFile.GetReferenceName(tag);
                entry.GroupTag.Value = tag.GroupTag.Tag;               // set the group tag

                lookup.Add(tag.Datum, entry);                          // add entry to the dictionary
                return(entry.Flags.Value = index);
            }

            return(entry.Flags.Value);
        }
예제 #6
0
        public override int Add(Blam.CacheIndex.Item tag)
        {
            int index = -1;

            Halo1.Tags.tag_database_entry_block entry;
            if (!lookup.TryGetValue(tag.Datum, out entry))             // hey, not in the database
            {
                string name = cacheFile.GetReferenceName(tag);

                index = db.Entries.Count;                               // count will be the index of our new entry
                db.Entries.Add(out entry);                              // add a new entry
                entry.Name.Value =                                      // set the name
                                   System.Text.Encoding.ASCII.GetBytes(name);
                entry.GroupTag.Value       = tag.GroupTag.Tag;          // set the group tag
                entry.HandleDataHigh.Value = name.GetHashCode();

                lookup.Add(tag.Datum, entry);                                   // add entry to the dictionary
                return(entry.Flags.Value = index);
            }

            return(entry.Flags.Value);
        }
        bool Extract(Blam.CacheExtractionInfo cei, Blam.DatumIndex tag_datum, bool remove_from_state)
        {
            if (remove_from_state)
            {
                // don't process it if it's already been done
                if (cacheFile.ExtractionState.Processed(tag_datum))
                {
                    return(true);
                }
                cacheFile.ExtractionState.Dequeue(tag_datum);
            }
            cacheFile.ExtractionState.CurrentTag = tag_datum;

            Blam.CacheIndex.Item ci = cacheFile.Index.Tags[tag_datum.Index];

            bool error = false;

            Blam.DatumIndex handle = Open(tag_datum);
            if (handle != Blam.DatumIndex.Null)
            {
                // we're about to extract, update our depth level
                cei.ExtractionDepth++;
                TagManager tm = Array[handle];

                #region read the tag from the cache
                try { tm.OpenForExtract(cei.Arguments.OutputDirectory, null); }
                catch (Exception ex) { extractionTrace.WriteLine("Failed to read tag, aborting extraction...'{0}.{1}'{2}{3}", tm.Name, tm.GroupTag.Name, Program.NewLine, ex); error = true; }
                #endregion

                #region if no errors
                if (!error)
                {
                    try { tm.Extract(); }
                    catch (Exception ex) { extractionTrace.WriteLine("Failed to write tag, aborting extraction...'{0}.{1}'{2}{3}", tm.Name, tm.GroupTag.Name, Program.NewLine, ex); error = true; }

                    tm.Close();
                }

                // something bad happened, so make sure we don't keep any bad tags
                if (error)
                {
                    System.IO.File.Delete(Path.Combine(cei.Arguments.OutputDirectory, tm.Name));
                }

                // process dependents if we want to
                if (!error && cei.Arguments.WithDependents)
                {
                    error = !ExtractWithDependents(cei, tm);
                }
                #endregion

                // we're done with the extraction process, update depth level
                cei.ExtractionDepth--;

                // create and write database
                if (cei.Arguments.OutputDatabase && cei.ExtractionDepth == 0)
                {
                    ExtractWriteTagDatabases(cei, tm);
                }

                Unload(handle);
            }
            else
            {
                error = true;
            }

            return(!error);
        }
예제 #8
0
 public CacheTagDatabase(CacheFile cf, Blam.CacheIndex.Item root_tag) : base(root_tag)
 {
     cacheFile = cf;
 }
        /// <summary>
        /// Open a tag in the cache file
        /// </summary>
        /// <param name="tag_datum">index of tag</param>
        /// <returns>
        /// The tag_index handle associated to the <see cref="TagManager"/> object used to open the tag,
        /// or <see cref="Blam.DatumIndex.Null"/> if this operations fails
        /// </returns>
        public Blam.DatumIndex Open(Blam.DatumIndex tag_datum)
        {
            if (tag_datum == Blam.DatumIndex.Null)
            {
                return(Blam.DatumIndex.Null);
            }


            Blam.CacheIndex.Item i = cacheFile.Index.Tags[tag_datum.Index];

            if (i.IsEmpty)
            {
                throw new ArgumentNullException("tag_datum", string.Format("The tag handle {0} references an empty tag. We can't open this!", tag_datum.ToString()));
            }

            // How can we open it if we don't know where it F*****G IS YOU C**T??
            if (i.Location != Blam.CacheIndex.ItemLocation.Internal && !i.IsFeignItem)
            {
                return(Blam.DatumIndex.Null);
            }

            // Is this tag already loaded? if so, reuse handle
            Blam.DatumIndex di = IsLoaded(i);
            if (di != Blam.DatumIndex.Null)
            {
                Array.IncrementReference(di);
                return(di);
            }

            TagManager tm = new TagManager(this);

            tm.ReferenceName = i.ReferenceName;             // sync the tag manager's name with the cache item's

            bool      group_tag_hack = false;
            BlamBuild build          = Engine.ToBuild();

            // HACK: Halo1 PC uses gbx's variant of the model tag
            if (Engine == BlamVersion.Halo1_CE && i.GroupTag == Blam.Halo1.TagGroups.mode)
            {
                tm.Manage(Blam.Halo1.TagGroups.mod2);
                group_tag_hack = true;
            }
            else
            // HACK: Halo 2/3 use a the 'sound' group tag for their 'cache_file_sound' definitions
#if !NO_HALO2
            if (build == BlamBuild.Halo2 && i.GroupTag == Blam.Halo2.TagGroups.snd_)
            {
                tm.Manage(Blam.Halo2.TagGroups.shit);
                group_tag_hack = true;
            }
            else
#endif
#if !NO_HALO3
            if (build == BlamBuild.Halo3 && i.GroupTag == Blam.Halo3.TagGroups.snd_)
            {
                tm.Manage(Blam.Halo3.TagGroups.shit);
                group_tag_hack = true;
            }
            else
#endif
#if !NO_HALO_ODST
            if (build == BlamBuild.HaloOdst && i.GroupTag == Blam.Halo3.TagGroups.snd_)
            {
                tm.Manage(Blam.Halo3.TagGroups.shit);
                group_tag_hack = true;
            }
            else
#endif
#if !NO_HALO_REACH
            if (build == BlamBuild.HaloReach && i.GroupTag == Blam.HaloReach.TagGroups.snd_)
            {
                tm.Manage(Blam.HaloReach.TagGroups.shit);
                group_tag_hack = true;
            }
            else
#endif
#if !NO_HALO4
            if (build == BlamBuild.Halo4 && i.GroupTag == Blam.Halo4.TagGroups.snd_)
            {
                tm.Manage(Blam.Halo4.TagGroups.shit);
                group_tag_hack = true;
            }
            else
#endif
            { tm.Manage(i.GroupTag); }

            if (!i.IsFeignItem)
            {
                // We don't care about this shit when extracting or opening from a cache file
                const uint k_open_flags = IO.ITagStreamFlags.DontTrackTagManagerReferences |
                                          IO.ITagStreamFlags.DontTrackTagReferencers;

                tm.Flags.Add(k_open_flags);

                try { tm.Read(i, cacheFile, group_tag_hack); }
                catch (Exception ex)
                {
                    indexTrace.WriteLine("Cache Index: Failed to open tag from cache: {0}{1}'{2}.{3}'{4}{5}",
                                         cacheFile.InputStream.FileName, Program.NewLine,
                                         cacheFile.GetReferenceName(i), i.GroupTag.Name, Program.NewLine, ex);
                    return(Blam.DatumIndex.Null);
                }

                // Remove the flag we set before reading
                tm.Flags.Remove(k_open_flags);
            }

            tm.TagIndex = Array.Add(tm);
            base.OnEventOpen(new TagIndexEventArgs(this, tm));
            return(tm.TagIndex);
        }
예제 #10
0
 /// <summary>
 /// Add a tag to the database using <paramref name="tag"/> as the root tag
 /// </summary>
 /// <param name="tag">Tag to use as the root tag when adding <paramref name="dependent_tag"/> to the database</param>
 /// <param name="dependent_tag">Tag which is directly referenced by <paramref name="tag"/></param>
 /// <returns>Hash value for tag's database entry</returns>
 /// <remarks>
 /// Does not modify the current root tag.
 /// <paramref name="tag"/> must already already exist in the database
 /// </remarks>
 public abstract int AddDependent(Blam.CacheIndex.Item tag, Blam.CacheIndex.Item dependent_tag);
예제 #11
0
 /// <summary>
 /// Add a tag to the database using the current root tag.
 /// </summary>
 /// <param name="dependent_tag">Tag which is directly referenced by the current root tag</param>
 /// <returns>Hash value for tag's database entry</returns>
 public int AddDependent(Blam.CacheIndex.Item dependent_tag)
 {
     return(AddDependent(root, dependent_tag));
 }
예제 #12
0
 /// <summary>
 /// Add a tag to the database
 /// </summary>
 /// <param name="tag"></param>
 /// <returns>Hash value for tag's database entry</returns>
 public abstract int Add(Blam.CacheIndex.Item tag);
예제 #13
0
 /// <summary>
 /// Initialize the tag database with a root tag
 /// </summary>
 /// <param name="root_tag"></param>
 protected CacheTagDatabase(Blam.CacheIndex.Item root_tag)
 {
     SetRoot(root_tag);
 }
예제 #14
0
 /// <summary>
 /// Set the current "root" tag of the database
 /// </summary>
 /// <param name="root_tag"></param>
 public void SetRoot(Blam.CacheIndex.Item root_tag)
 {
     Add(root = root_tag);
 }