Пример #1
0
        public MainForm()
        {
            testToolStripMenuItem_Click(null, null);

            if (Properties.Settings.Default.ProjectsDirectory == null)
                Properties.Settings.Default.ProjectsDirectory = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments), "Sunfish 2011\\Projects");
            if(!Directory.Exists(Properties.Settings.Default.ProjectsDirectory))
                Directory.CreateDirectory(Properties.Settings.Default.ProjectsDirectory);

            InitializeComponent();

            LoadDefaultWorkspace(); 

            #region Status Handler

            Globals.StatusChangeHandler s = new Globals.StatusChangeHandler(Status);
            Globals.StatusChanged += s;



            #endregion

            #region Dialogs Initialization

            openMapDialog = new OpenFileDialog();
            openMapDialog.Filter = "Halo 2 Cache File (*.map) | *.map";

            openProjectDialog = new OpenFileDialog();
            openProjectDialog.Filter = "Sunfish Project File (*.h2proj) | *.h2proj";
            openProjectDialog.InitialDirectory = Properties.Settings.Default.ProjectsDirectory;

            saveTagDialog = new SaveFileDialog();
            saveTagDialog.Filter = "Sunfish Tag File (*.sf) | *.sf";
            saveFilters = new Dictionary<string, int>(Index.Types.Length);
            for (int i = 0; i < Index.Types.Length; i++)
            {
                saveFilters.Add(Index.Types[i].ToString(), i + 2);
                saveTagDialog.Filter += String.Format("|Sunfish {0} File (*.{1}.sf) | *.{1}.sf", Index.Types[i].ToString(), Index.Types[i].ToPathSafeString());
            }
            saveTagDialog.SupportMultiDottedExtensions = true;
            saveTagDialog.AddExtension = true;

            #endregion

            #region auto load
#if DEBUG
            project = new Project();
            project.Load(@"O:\Sunfish 2011\Projects\taco\taco.h2proj");
            LoadProject();
#endif
            #endregion
        }
Пример #2
0
 public void Compile(Project project, bool rebuildcaches)
 {
     List<string> filenames = new List<string>(Directory.GetFiles(project.SourceDirectory, String.Format("*{0}", Sunfish.Tag.Path.Extension), SearchOption.AllDirectories));
     project.SourceFiles = new List<string>(filenames);
     //for(int i=0;i<project.SourceFiles.Count;i++)
     //    project.SourceFiles[i] = project.SourceFiles[i].Substring(project.SourceDirectory.Length);
     project.SortSourceFiles();
     Benchmark mark = new Benchmark();
     mark.Begin();
     if (!rebuildcaches && CheckCacheStatus(project)) { LoadCaches(project); }
     else CreateCaches(project);
     CreateMap(project);
     mark.End();
     System.Windows.Forms.MessageBox.Show(String.Format("finished in: {0}", mark.Result), "Solution Compiled");
 }
Пример #3
0
 private void LoadCaches(Project project)
 {
     SoundCache.Load(Path.Combine(project.BinDirectory, "SOUND_RAW_CACHE.BIN"));
     ModelCache.Load(Path.Combine(project.BinDirectory, "MODEL_RAW_CACHE.BIN"));
     SbspCache.Load(Path.Combine(project.BinDirectory, "STRUCTURE_RAW_CACHE.BIN"));
     LtmpCache.Load(Path.Combine(project.BinDirectory, "LIGHTMAP_RAW_CACHE.BIN"));
     DECRCache.Load(Path.Combine(project.BinDirectory, "DECORATER_RAW_CACHE.BIN"));
     WeatherCache.Load(Path.Combine(project.BinDirectory, "WEATHER_RAW_CACHE.BIN"));
     AnimationCache.Load(Path.Combine(project.BinDirectory, "ANIMATION_RAW_CACHE.BIN"));
     BitmapCache.Load(Path.Combine(project.BinDirectory, "TEXTURE_RAW_CACHE.BIN"));
     StringIDsCache.Load(Path.Combine(project.BinDirectory, "STRINGS_CACHE.BIN"));
     IndexCache.Load(Path.Combine(project.BinDirectory, "INDEX.BIN"));
     TagnameCache.Load(Path.Combine(project.BinDirectory, "TAGNAMES.BIN"));
     EnglishUnicodeCache.Load(Path.Combine(project.BinDirectory, "ENGLISH_UNICODE.BIN"));
     MetaCache.Load(Path.Combine(project.BinDirectory, "META.BIN"));
     SbspLtmpMetaCache.Load(Path.Combine(project.BinDirectory, "STRUCTURE_LIGHTMAP_META.BIN"));
     Header = new Header(File.OpenRead(Path.Combine(project.BinDirectory, "HEADER.BIN")));
 }
Пример #4
0
 public void Load(string filename)
 {
     Globals.Status = "Loading Project...";
     XmlReader xmlReader = XmlReader.Create(filename);
     while (xmlReader.Read())
         if (xmlReader.NodeType == XmlNodeType.Element)
         {
             switch (xmlReader.LocalName)
             {
                 case "Project":
                     Name = xmlReader.GetAttribute("name");
                     Scenario = xmlReader.GetAttribute("scenario");
                     CacheCreationDate = DateTime.FromBinary(long.Parse(xmlReader.GetAttribute("cache")));
                     break;
                 case "RootDirectory":
                     RootDirectory = xmlReader.GetAttribute("path");
                     break;
                 case "Includes":
                     XmlReader filesReader = xmlReader.ReadSubtree();
                     filesReader.Read();
                     while (filesReader.Read())
                     {
                         if (filesReader.NodeType == XmlNodeType.Element)
                         {
                             switch (filesReader.LocalName)
                             {
                                 case "include":
                                     string fName = filesReader.GetAttribute("path");
                                     Includes.Add(fName);
                                     break;
                             }
                         }
                     }
                     break;
             }
         }
     xmlReader.Close();
     SourceFiles = new List<string>(Directory.GetFiles(SourceDirectory, String.Format("*{0}", Sunfish.Tag.Path.Extension), SearchOption.AllDirectories));
     SortSourceFiles();
     List<CompilerTag> Tags = new List<CompilerTag>(SourceFiles.Count);
     Directory.SetCurrentDirectory(SourceDirectory);
     foreach (string filepath in SourceFiles)
         Tags.Add(new CompilerTag(filepath));
     Strings = new List<string>(10000);
     Strings.AddRange(Sunfish.Developmental.GlobalStringIDs.Values);
     foreach (CompilerTag tag in Tags)
         foreach (string str in tag.Strings)
             if (!Strings.Contains(str)) Strings.Add(str);
     CurrentProject = this;
     Globals.ClearStatus();
 }
Пример #5
0
 public static Project Create(string path, string name)
 {
     if (!Directory.Exists(path)) throw new Exception();
     Project p = new Project();
     p.RootDirectory = path;
     p.Name = name;
     Directory.CreateDirectory(p.SourceDirectory);
     Directory.CreateDirectory(p.BinDirectory);
     XmlWriter xmlWriter = XmlWriter.Create(Path.Combine(p.RootDirectory, Path.ChangeExtension(name, ".h2proj")));
     xmlWriter.WriteStartDocument();
     xmlWriter.WriteStartElement("Project");
     xmlWriter.WriteAttributeString("name", name);
     xmlWriter.WriteAttributeString("cache", DateTime.MinValue.ToBinary().ToString());
     xmlWriter.WriteStartElement("RootDirectory");
     xmlWriter.WriteAttributeString("path", p.RootDirectory);
     xmlWriter.WriteEndElement();
     xmlWriter.WriteStartElement("Includes");
     xmlWriter.WriteEndElement();
     xmlWriter.WriteEndDocument();
     xmlWriter.Close();
     return p;
 }
Пример #6
0
 private void openProjectToolStripMenuItem_Click(object sender, EventArgs e)
 {
     if (openProjectDialog.ShowDialog() == DialogResult.OK)
     {
         if (project != null) { CloseProject(); }
         project = new Project();
         project.Load(openProjectDialog.FileName);
         LoadProject();
     }
 }
Пример #7
0
 private void CloseProject()
 {
     if (project != null)
     {
         project.Save();
         Explorer.SaveLayout(Path.Combine(project.RootDirectory, "user.settings"));
         project = null;
         this.Text = "Sunfish 2011";
         Explorer.treeView1.Nodes.Clear();
         projectToolStripMenuItem.Enabled = false;
         projectToolStripMenuItem.Visible = false;
         buildToolStripMenuItem.Enabled = false;
         buildToolStripMenuItem.Visible = false;
         closeProjectToolStripMenuItem.Enabled = false;
     }
 }
Пример #8
0
 private void newProjectToolStripMenuItem_Click(object sender, EventArgs e)
 {
     CreateFileDialog cfd = new CreateFileDialog("New Project");
     if (cfd.ShowDialog() == DialogResult.OK)
     {
         project = Project.Create(Path.Combine(Properties.Settings.Default.ProjectsDirectory, cfd.FileName), cfd.FileName);
         LoadProject();
     }
 }
Пример #9
0
 private bool CheckCacheStatus(Project project)
 {
     return (File.Exists(Path.Combine(project.BinDirectory, "SOUND_RAW_CACHE.BIN")) && File.GetLastWriteTime(Path.Combine(project.BinDirectory, "SOUND_RAW_CACHE.BIN")) == project.CacheCreationDate
        && File.Exists(Path.Combine(project.BinDirectory, "MODEL_RAW_CACHE.BIN")) && File.GetLastWriteTime(Path.Combine(project.BinDirectory, "MODEL_RAW_CACHE.BIN")) == project.CacheCreationDate
        && File.Exists(Path.Combine(project.BinDirectory, "STRUCTURE_RAW_CACHE.BIN")) && File.GetLastWriteTime(Path.Combine(project.BinDirectory, "STRUCTURE_RAW_CACHE.BIN")) == project.CacheCreationDate
        && File.Exists(Path.Combine(project.BinDirectory, "LIGHTMAP_RAW_CACHE.BIN")) && File.GetLastWriteTime(Path.Combine(project.BinDirectory, "LIGHTMAP_RAW_CACHE.BIN")) == project.CacheCreationDate
        && File.Exists(Path.Combine(project.BinDirectory, "DECORATER_RAW_CACHE.BIN")) && File.GetLastWriteTime(Path.Combine(project.BinDirectory, "DECORATER_RAW_CACHE.BIN")) == project.CacheCreationDate
        && File.Exists(Path.Combine(project.BinDirectory, "WEATHER_RAW_CACHE.BIN")) && File.GetLastWriteTime(Path.Combine(project.BinDirectory, "WEATHER_RAW_CACHE.BIN")) == project.CacheCreationDate
        && File.Exists(Path.Combine(project.BinDirectory, "ANIMATION_RAW_CACHE.BIN")) && File.GetLastWriteTime(Path.Combine(project.BinDirectory, "ANIMATION_RAW_CACHE.BIN")) == project.CacheCreationDate
        && File.Exists(Path.Combine(project.BinDirectory, "TEXTURE_RAW_CACHE.BIN")) && File.GetLastWriteTime(Path.Combine(project.BinDirectory, "TEXTURE_RAW_CACHE.BIN")) == project.CacheCreationDate
        && File.Exists(Path.Combine(project.BinDirectory, "STRINGS_CACHE.BIN")) && File.GetLastWriteTime(Path.Combine(project.BinDirectory, "STRINGS_CACHE.BIN")) == project.CacheCreationDate
        && File.Exists(Path.Combine(project.BinDirectory, "INDEX.BIN")) && File.GetLastWriteTime(Path.Combine(project.BinDirectory, "INDEX.BIN")) == project.CacheCreationDate
        && File.Exists(Path.Combine(project.BinDirectory, "TAGNAMES.BIN")) && File.GetLastWriteTime(Path.Combine(project.BinDirectory, "TAGNAMES.BIN")) == project.CacheCreationDate
        && File.Exists(Path.Combine(project.BinDirectory, "ENGLISH_UNICODE.BIN")) && File.GetLastWriteTime(Path.Combine(project.BinDirectory, "ENGLISH_UNICODE.BIN")) == project.CacheCreationDate
        && File.Exists(Path.Combine(project.BinDirectory, "META.BIN")) && File.GetLastWriteTime(Path.Combine(project.BinDirectory, "META.BIN")) == project.CacheCreationDate
        && File.Exists(Path.Combine(project.BinDirectory, "STRUCTURE_LIGHTMAP_META.BIN")) && File.GetLastWriteTime(Path.Combine(project.BinDirectory, "STRUCTURE_LIGHTMAP_META.BIN")) == project.CacheCreationDate
        && File.Exists(Path.Combine(project.BinDirectory, "HEADER.BIN")) && File.GetLastWriteTime(Path.Combine(project.BinDirectory, "HEADER.BIN")) == project.CacheCreationDate);
 }
Пример #10
0
 public void Compile(Project project)
 {
     Compile(project, false);
 }
Пример #11
0
        public void CreateMap(Project project)
        {
            FileStream output = new FileStream(Path.ChangeExtension(Path.Combine(project.BinDirectory, project.Name), ".map"), FileMode.Create, FileAccess.ReadWrite, FileShare.None);
            using (output)
            {
                BinaryWriter bw = new BinaryWriter(output);

                output.Position = SoundCache.Offset;
                SoundCache.Stream.WriteTo(output);

                output.Position = ModelCache.Offset;
                ModelCache.Stream.WriteTo(output);

                output.Position = SbspCache.Offset;
                SbspCache.Stream.WriteTo(output);

                output.Position = LtmpCache.Offset;
                LtmpCache.Stream.WriteTo(output);

                output.Position = DECRCache.Offset;
                DECRCache.Stream.WriteTo(output);

                output.Position = WeatherCache.Offset;
                WeatherCache.Stream.WriteTo(output);

                output.Position = AnimationCache.Offset;
                AnimationCache.Stream.WriteTo(output);

                output.Position = SbspLtmpMetaCache.Offset;
                SbspLtmpMetaCache.WriteTo(output);

                output.Position = StringIDsCache.Offset;
                StringIDsCache.WriteTo(output, ref Header);
                output.Position = Padding.Pad(output.Position);

                output.Position = TagnameCache.Offset;
                TagnameCache.WriteIndexTo(output, ref Header);
                TagnameCache.WriteTableTo(output, ref Header);
                output.Position = Padding.Pad(output.Position);

                output.Position = EnglishUnicodeCache.Offset;
                EnglishUnicodeCache.WriteUnicodeIndexTo(output);
                EnglishUnicodeCache.WriteUnicodeTableTo(output);
                output.Position = Padding.Pad(output.Position);

                output.Position = BitmapCache.Offset;
                BitmapCache.Stream.WriteTo(output);

                output.Position = IndexCache.Offset;
                IndexCache.WriteTo(output, ref Header, IndexCache.Entries[0].Index, IndexCache.Entries[3].Index);

                output.Position = MetaCache.Offset;
                MetaCache.Stream.WriteTo(output);
                bw.Write(Padding.GetBytes(output.Position, 2048));

                Header.Checksum = CalculateChecksum(output);
                Header.TagCacheLength = MetaCache.Length;
                Header.TotalCacheLength = MetaCache.Length + SbspLtmpMetaCache.Length + IndexCache.Length;

                output.Position = 0;
                bw.Write(Header.ToByteArray());
            }
        }
Пример #12
0
        public void CreateCaches(Project project)
        {
            #region STAGE ONE - Load Data To Caches

            #region Load Tags

            Tags = new List<CompilerTag>(project.SourceFiles.Count);
            Directory.SetCurrentDirectory(project.SourceDirectory);
            foreach (string filename in project.SourceFiles)
                Tags.Add(new CompilerTag(filename));

            #endregion

            Header = new Header() { Type = Header.MapType.Multiplayer, Name = project.Name, Scenario = project.Scenario };

            foreach (CompilerTag tag in Tags)
            { 
                #region Cache StringReference Values

                StringIDsCache.CacheData(tag);

                #endregion

                #region Process Unicode Tags

                if (tag.Type == "utf8")
                    EnglishUnicodeCache.CacheData(tag, StringIDsCache);

                #endregion

                #region Initialize Tag in Filetable and Index

                TagnameCache.CacheData(tag);
                IndexCache.CacheData(tag);

                #endregion

                #region Cache Resource Data

                switch (tag.Type)
                {
                    case "ugh!":
                        SoundCache.CacheData(tag);
                        break;
                    case "mode":
                        ModelCache.CacheData(tag);
                        break;
                    case "sbsp":
                        SbspCache.CacheData(tag);
                        break;
                    case "ltmp":
                        LtmpCache.CacheData(tag);
                        break;
                    case "DECR":
                        DECRCache.CacheData(tag);
                        break;
                    case "weat":
                        WeatherCache.CacheData(tag);
                        break;
                    case "jmad":
                        AnimationCache.CacheData(tag);
                        break;
                    case "bitm":
                        BitmapCache.CacheData(tag);
                        break;
                }

                #endregion

                #region Cache Tag Data

                switch (tag.Type)
                {
                    case "sbsp":
                        SbspLtmpMetaCache.CacheData(tag);
                        break;
                    case "ltmp":
                        SbspLtmpMetaCache.CacheData(tag);
                        break;
                    default:
                        MetaCache.CacheData(tag);
                        break;

                }
                #endregion
            }

            #endregion

            #region STAGE TWO - Setup And Sort Caches
            
            SoundCache.Offset = 2048;
            ModelCache.Offset = SoundCache.NextOffset;
            SbspCache.Offset = ModelCache.NextOffset;
            LtmpCache.Offset = SbspCache.NextOffset;
            DECRCache.Offset = LtmpCache.NextOffset;
            WeatherCache.Offset = DECRCache.NextOffset;
            AnimationCache.Offset = WeatherCache.NextOffset;
            SbspLtmpMetaCache.Offset = AnimationCache.NextOffset;

            #region Update Scenario Tag

            SbspLtmpMetaCache.SetVirtualOffset(IndexCache.NextVirtualOffset);
            SbspLtmpMetaCache.UpdateScenario(Tags[3]);
            MetaCache[3] = Tags[3].TagStream.ToArray();

            #endregion

            StringIDsCache.Offset = SbspLtmpMetaCache.NextOffset;
            TagnameCache.Offset = StringIDsCache.NextOffset;
            EnglishUnicodeCache.Offset = TagnameCache.NextOffset;
            BitmapCache.Offset = EnglishUnicodeCache.NextOffset;
            IndexCache.Offset = BitmapCache.NextOffset;
            MetaCache.Offset = IndexCache.NextOffset;

            #region Update Globals with Unicode information

            BinaryWriter bw = new BinaryWriter(Tags[0].TagStream);
            Tags[0].TagStream.Seek(400, SeekOrigin.Begin);
            bw.Write(EnglishUnicodeCache.Values.Count);
            bw.Write(EnglishUnicodeCache.UnicodeTableLength);
            bw.Write(EnglishUnicodeCache.UnicodeIndexOffset);
            bw.Write(EnglishUnicodeCache.UnicodeTableOffset);
            Tags[0].TagStream.Seek(4, SeekOrigin.Current);
            for (int i = 0; i < 8; i++)
            {
                Tags[0].TagStream.Seek(8, SeekOrigin.Current);
                bw.Write(new byte[8]);
                bw.Write(BitmapCache.Offset);
                bw.Write(BitmapCache.Offset);
                Tags[0].TagStream.Seek(4, SeekOrigin.Current);
            }
            MetaCache[0] = Tags[0].TagStream.ToArray();

            #endregion

            #region Set Virtual Addresses

            MetaCache.VirtualOffset = SbspLtmpMetaCache.NextVirtualOffset;

            #endregion

            #region Update IndexCache

            SbspLtmpMetaCache.UpdateIndexCache(IndexCache);
            MetaCache.UpdateIndexCache(IndexCache);

            #endregion

            #endregion

            #region STAGE THREE - Update Meta Values

            foreach (CompilerTag tag in Tags)
            {
                BinaryReader br;
                MetaCache Cache = null;

                if (SbspLtmpMetaCache.TagIndexers.Contains(tag.ID))
                    Cache = SbspLtmpMetaCache;
                else if (MetaCache.TagIndexers.Contains(tag.ID))
                    Cache = MetaCache;
                else throw new Exception();

                br = new BinaryReader(Cache.Stream);
                bw = new BinaryWriter(Cache.Stream);

                int Index = Cache.TagIndexers.IndexOf(tag.ID);

                RawCache ResourceCache = null;
                switch (tag.Type)
                {
                    case "ugh!":
                        ResourceCache = SoundCache;
                        break;
                    case "mode":
                        ResourceCache = ModelCache;
                        break;
                    case "sbsp":
                        ResourceCache = SbspCache;
                        break;
                    case "ltmp":
                        ResourceCache = LtmpCache;
                        break;
                    case "DECR":
                        ResourceCache = DECRCache;
                        break;
                    case "weat":
                        ResourceCache = WeatherCache;
                        break;
                    case "jmad":
                        ResourceCache = AnimationCache;
                        break;
                    case "bitm":
                        ResourceCache = BitmapCache;
                        break;
                }

                #region Update Pointers and Other Values

                valueCache.Clear();
                pointerCache.Clear();
                Block block = Blocks.Types[tag.Type];
                ProcessBlock(block, 1, 0, tag.TagStream);

                for (int i = 0; i < pointerCache.Count; i++)
                {
                    Cache.Stream.Position = Cache.Entries[Index].Offset + pointerCache.Values[i].Offset;
                    int address = br.ReadInt32();
                    if (address != -1)
                    {
                        Cache.Stream.Seek(-4, SeekOrigin.Current);
                        bw.Write(IndexCache.Entries[tag.ID].Address + address);
                    }
                }

                for (int i = 0; i < valueCache.Count; i++)
                {
                    switch (valueCache.Values[i].Type)
                    {
                        case Value.ValueType.StringId:
                            Cache.Stream.Position = Cache.Entries[Index].Offset + valueCache.Values[i].Offset;
                            int index = br.ReadInt32();
                            Cache.Stream.Seek(-4, SeekOrigin.Current);
                            StringId strRef = new StringId((short)StringIDsCache.Values.IndexOf(tag.Strings[index]), (sbyte)Encoding.UTF8.GetByteCount(tag.Strings[index]));
                            bw.Write(strRef);
                            break;
                            TagIndex tagIndex;
                        case Value.ValueType.TagId:
                            Cache.Stream.Position = Cache.Entries[Index].Offset + valueCache.Values[i].Offset;
                            index = br.ReadInt32();
                            if (index == -1) continue;
                            Cache.Stream.Seek(-4, SeekOrigin.Current);
                            tagIndex = IndexCache.Entries[TagnameCache.Tagnames.IndexOf(tag.TagReferences[index])].Index;
                            bw.Write(tagIndex);
                            break;
                        case Value.ValueType.TagReference:
                            Cache.Stream.Position = Cache.Entries[Index].Offset + valueCache.Values[i].Offset + 4;
                            index = br.ReadInt32();
                            if (index == -1) continue;
                            Cache.Stream.Seek(-8, SeekOrigin.Current);
                            byte[] bytes = Encoding.UTF8.GetBytes(Globals.ReverseString(Sunfish.Index.GetDirtyType(Tag.Path.GetTagType(tag.TagReferences[index]))));
                            bw.Write(bytes, 0, 4);
                            tagIndex = IndexCache.Entries[TagnameCache.Tagnames.IndexOf(tag.TagReferences[index])].Index;
                            bw.Write(tagIndex);
                            break;
                    }
                }

                #endregion

                #region Update Resource Values

                if (tag.ResourceInformation.Length > 0)
                {
                    rawCache.Clear();
                    ProcessBlockRaw(block, 1, 0, tag.TagStream);

                    int ResourceCacheIndex = ResourceCache.TagIDs.IndexOf(tag.ID);
                    int ResourceIndex = 0;
                    for (int i = 0; i < rawCache.Count; i++)
                    {
                        Cache.Stream.Position = Cache.Entries[Index].Offset + rawCache.Values[i].Offset1;
                        int address = br.ReadInt32();
                        if (!(address == -1 || Globals.IsExternalResource(address)))
                        {
                            Cache.Stream.Seek(-4, SeekOrigin.Current);
                            bw.Write(ResourceCache.Offset + ResourceCache.Tags[ResourceCacheIndex].Offset + tag.ResourceInformation[ResourceIndex].Address);
                            Cache.Stream.Position = Cache.Entries[Index].Offset + rawCache.Values[i].Offset0;
                            bw.Write(tag.ResourceInformation[ResourceIndex].Length);
                            ResourceIndex++;
                        }
                    }
                }

                #endregion
            }

            #endregion

            #region STAGE FOUR - Save Caches

            project.CacheCreationDate = DateTime.Now;
            SoundCache.Save(Path.Combine(project.BinDirectory, "SOUND_RAW_CACHE.BIN"), project.CacheCreationDate);
            ModelCache.Save(Path.Combine(project.BinDirectory, "MODEL_RAW_CACHE.BIN"), project.CacheCreationDate);
            SbspCache.Save(Path.Combine(project.BinDirectory, "STRUCTURE_RAW_CACHE.BIN"), project.CacheCreationDate);
            LtmpCache.Save(Path.Combine(project.BinDirectory, "LIGHTMAP_RAW_CACHE.BIN"), project.CacheCreationDate);
            DECRCache.Save(Path.Combine(project.BinDirectory, "DECORATER_RAW_CACHE.BIN"), project.CacheCreationDate);
            WeatherCache.Save(Path.Combine(project.BinDirectory, "WEATHER_RAW_CACHE.BIN"), project.CacheCreationDate);
            AnimationCache.Save(Path.Combine(project.BinDirectory, "ANIMATION_RAW_CACHE.BIN"), project.CacheCreationDate);
            BitmapCache.Save(Path.Combine(project.BinDirectory, "TEXTURE_RAW_CACHE.BIN"), project.CacheCreationDate);
            StringIDsCache.Save(Path.Combine(project.BinDirectory, "STRINGS_CACHE.BIN"), project.CacheCreationDate);
            IndexCache.Save(Path.Combine(project.BinDirectory, "INDEX.BIN"), project.CacheCreationDate);
            TagnameCache.Save(Path.Combine(project.BinDirectory, "TAGNAMES.BIN"), project.CacheCreationDate);
            EnglishUnicodeCache.Save(Path.Combine(project.BinDirectory, "ENGLISH_UNICODE.BIN"), project.CacheCreationDate);
            MetaCache.Save(Path.Combine(project.BinDirectory, "META.BIN"), project.CacheCreationDate);
            SbspLtmpMetaCache.Save(Path.Combine(project.BinDirectory, "STRUCTURE_LIGHTMAP_META.BIN"), project.CacheCreationDate);
            using (FileStream file = new FileStream(Path.Combine(project.BinDirectory, "HEADER.BIN"), FileMode.Create, FileAccess.Write, FileShare.ReadWrite | FileShare.Delete))
            {
                byte[] buffer = Header.ToByteArray();
                file.Write(buffer, 0, buffer.Length);
            }
            File.SetLastWriteTime(Path.Combine(project.BinDirectory, "HEADER.BIN"), project.CacheCreationDate);
            project.Save();

            #endregion
        }