Exemple #1
0
        /// <summary>
        /// Gets a audio file from a DBPF using its InstanceID.
        /// </summary>
        /// <param name="InstanceID">The InstanceID of the audio.</param>
        /// <param name="dbpf">The DBPF to search.</param>
        /// <returns>The audio as a stream of bytes.</returns>
        private byte[] GetAudioFrom(uint InstanceID, DBPFFile dbpf)
        {
            if (InstanceID == 0)
            {
                return(null);
            }

            //all game sfx has type id 0x2026960B
            byte[] dat = dbpf.GetItemByID((ulong)DBPFTypeID.SoundFX + (((ulong)InstanceID) << 32));

            if (dat != null)
            {
                string head = new string(new char[] { (char)dat[0], (char)dat[1], (char)dat[2], (char)dat[3] });
                if (head.StartsWith("XA"))
                {
                    return(new XAFile(dat).DecompressedData);
                }
                else if (head.StartsWith("UTM0"))
                {
                    var utk = new UTKFile2(dat);
                    utk.UTKDecode();
                    return(utk.DecompressedWav);
                }
                else
                {
                    return(dat); //either wav or mp3, bass.net can explicitly read these.
                }
            }
            else
            {
                Debug.WriteLine("Couldn't find sound!");
            }
            return(null);
        }
Exemple #2
0
        /*
         * public DIREntry GetEntryByID(EntryRef ID)
         * {
         *  if (m_EntryByID.ContainsKey(ID))
         *      return m_EntryByID[ID];
         *  else
         *      return null;
         * }*/
        public static void Read(DBPFFile package, byte[] file)
        {
            var gGroupID = Hash.GroupHash(Path.GetFileNameWithoutExtension(package.fname));
            var stream   = new MemoryStream(file);
            var reader   = IoBuffer.FromStream(stream, ByteOrder.LITTLE_ENDIAN);

            //var count = 0;
            while (stream.Position < file.Length)
            {
                var TypeID  = reader.ReadUInt32();
                var GroupID = reader.ReadUInt32();
                if (GroupID == 0xFFFFFFFF && package.fname != "")
                {
                    GroupID = gGroupID;
                }
                var  InstanceID  = reader.ReadUInt32();
                uint InstanceID2 = 0x00000000;
                if (package.IndexMinorVersion >= 2)
                {
                    InstanceID2 = reader.ReadUInt32();
                }
                var idEntry2 = Hash.TGIRHash(InstanceID, InstanceID2, TypeID, GroupID);
                package.GetEntryByFullID(idEntry2).uncompressedSize = reader.ReadUInt32();

                /*
                 * if (!m_EntryByFullID.ContainsKey(idEntry2))
                 *  m_EntryByFullID.Add(idEntry2, entry);
                 * entry.UncompressedFileSize = reader.ReadUInt32();
                 * count += 1;*/
            }
            reader.Dispose();
            stream.Dispose();
        }
        private void WriteAndCommit(string filename, Stream outfile, DBPFFile dbfile, Dictionary <DBPFReference, KeyValuePair <DBPFIndexEntry, byte[]> > toreplace, List <KeyValuePair <DBPFIndexEntry, byte[]> > toadd)
        {
            dbfile.Write(outfile, delegate(ref DBPFIndexEntry entry, ref byte[] data)
            {
                KeyValuePair <DBPFIndexEntry, byte[]> replacement;
                if (toreplace.TryGetValue(entry.Reference, out replacement))
                {
                    entry = replacement.Key;
                    data  = replacement.Value;
                }
            }, toadd);

            foreach (DBPFReference commitref in toreplace.Keys)
            {
                StubbleSource source = new StubbleSource();
                source.SourceFile  = filename;
                source.SourceTable = commitref;
                mData.CommitModifiedData((Languages)(commitref.Instance >> 56), source);
            }
            foreach (KeyValuePair <DBPFIndexEntry, byte[]> commitentry in toadd)
            {
                StubbleSource source = new StubbleSource();
                source.SourceFile  = filename;
                source.SourceTable = commitentry.Key.Reference;
                mData.CommitModifiedData((Languages)(commitentry.Key.Reference.Instance >> 56), source);
            }
        }
Exemple #4
0
 public static void LoadArchives(List <string> archives, bool setLoadFinishedToTrue = false)
 {
     foreach (var element1 in config.dlc)
     {
         foreach (var element in archives)
         {
             var fil = Path.Combine(config.game_dir, element1, element);
             if (File.Exists(fil))
             {
                 DBPFFile.LoadResource(fil);
             }
             else
             {
                 if (Directory.Exists(fil))
                 {
                     DirectoryInfo folderInfo = new DirectoryInfo(fil);
                     foreach (var file in folderInfo.GetFiles("*.package"))
                     {
                         DBPFFile.LoadResource(file.FullName);
                     }
                 }
             }
         }
     }
     if (setLoadFinishedToTrue)
     {
         LoadFinished = true;
     }
 }
Exemple #5
0
        public static void Read(DBPFFile package, byte[] file)
        {
            var gGroupID = package.groupID;
            var stream   = new MemoryStream(file);
            var reader   = IoBuffer.FromStream(stream, ByteOrder.LITTLE_ENDIAN);

            while (stream.Position < file.Length)
            {
                var TypeID  = reader.ReadUInt32();
                var GroupID = reader.ReadUInt32();
                if (GroupID == 0xFFFFFFFF && package.fname != "")
                {
                    GroupID = gGroupID;
                }
                var  InstanceID  = reader.ReadUInt32();
                uint InstanceID2 = 0x00000000;
                if (package.IndexMinorVersion >= 2)
                {
                    InstanceID2 = reader.ReadUInt32();
                }
                var idEntry2 = Hash.TGIRHash(InstanceID, InstanceID2, TypeID, GroupID);
                package.GetEntryByFullID(idEntry2).uncompressedSize = reader.ReadUInt32();
            }
            reader.Dispose();
            stream.Dispose();
        }
Exemple #6
0
        /// <summary>
        /// Gets a track from a DBPF using its InstanceID.
        /// </summary>
        /// <param name="dbpf">The DBPF to search.</param>
        private void AddTracksFrom(DBPFFile dbpf)
        {
            var tracks = dbpf.GetItemsByType(DBPFTypeID.TRK);

            for (var i = 0; i < tracks.Count; i++)
            {
                TracksById.Add(tracks[i].Key, new Track(tracks[i].Value));
            }
        }
        public void Export(IWin32Window owner)
        {
            string origfilename = null;
            bool   cleanup      = false;

            try
            {
                try
                {
                    Stream outfile;
                    OpenOrCreate(mFilename, out origfilename, out cleanup, out outfile);

                    using (outfile)
                    {
                        DBPFFile dbfile;
                        if (origfilename == null)
                        {
                            dbfile = new DBPFFile();
                        }
                        else
                        {
                            dbfile = new DBPFFile(origfilename);
                        }

                        using (dbfile)
                        {
                            if (dbfile.IsProtected)
                            {
                                MessageBox.Show(owner, "Saving to protected DB files not allowed", "Save Error", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
                                return;
                            }

                            Dictionary <DBPFReference, KeyValuePair <DBPFIndexEntry, byte[]> > toreplace = new Dictionary <DBPFReference, KeyValuePair <DBPFIndexEntry, byte[]> >();
                            List <KeyValuePair <DBPFIndexEntry, byte[]> > toadd = new List <KeyValuePair <DBPFIndexEntry, byte[]> >();

                            GatherSaveData(dbfile, toreplace, toadd);

                            // Write the new file
                            WriteAndCommit(mFilename, outfile, dbfile, toreplace, toadd);
                        }
                    }
                    if (origfilename != null)
                    {
                        File.Delete(origfilename);
                    }
                    cleanup = false;
                }
                catch (Exception ex)
                {
                    MessageBox.Show(owner, string.Format("Error saving package:\n{0}", ex.Message), "Save Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                }
            }
            finally
            {
                PerformCleanup(mFilename, origfilename, cleanup);
            }
        }
Exemple #8
0
    private void Start()
    {
        Debug.Log(Path.Combine(Application.dataPath, "config.json"));
        var conf = JsonUtility.FromJson <Config>(File.ReadAllText(Path.Combine(Application.dataPath, "config.json")));

        var pack = new DBPFFile(conf.package_dir);

        Debug.Log("Entries in this file(" + conf.package_dir + "): " + pack.NumEntries);
        var modelPack = new DBPFFile(conf.model_dir);
    }
Exemple #9
0
        /// <summary>
        /// Initializes the audio manager.
        /// </summary>
        public void Init()
        {
            this.Stations     = new List <AudioReference>();
            this.StationsById = new Dictionary <uint, AudioReference>();
            this.Modes        = new List <AudioReference>();

            var stationsRegEx = new Regex(@"music/stations/.*\.mp3");

            foreach (var file in ContentManager.AllFiles)
            {
                if (stationsRegEx.IsMatch(file))
                {
                    var reference = new AudioReference {
                        Type = AudioType.RADIO_STATION, FilePath = ContentManager.GetPath(file)
                    };
                    Stations.Add(reference);
                    var idString = Path.GetFileNameWithoutExtension(file);
                    idString = idString.Substring(idString.LastIndexOf("_") + 1);
                    var id = Convert.ToUInt32(idString, 16);
                    reference.ID = id;
                    StationsById.Add(id, reference);
                }
            }

            TSOAudio = new DBPFFile(ContentManager.GetPath("TSOAudio.dat"));
            tsov2    = new DBPFFile(ContentManager.GetPath("tsov2.dat"));
            Stings   = new DBPFFile(ContentManager.GetPath("Stings.dat"));
            EP5Samps = new DBPFFile(ContentManager.GetPath("EP5Samps.dat"));
            EP2      = new DBPFFile(ContentManager.GetPath("EP2.dat"));
            Hitlists = new DBPFFile(ContentManager.GetPath("HitListsTemp.dat"));

            SFXCache         = new Dictionary <uint, SoundEffect>();
            TracksById       = new Dictionary <uint, Track>();
            TracksByBackupId = new Dictionary <uint, Track>();
            HitlistsById     = new Dictionary <uint, Hitlist>();

            AddTracksFrom(TSOAudio);

            //load events
            _Events = new Dictionary <string, HITEventRegistration>();
            var content       = ContentManager;
            var newmain       = LoadHitGroup(content.GetPath("sounddata/newmain.hit"), content.GetPath("sounddata/eventlist.txt"), content.GetPath("sounddata/newmain.hsm"));
            var relationships = LoadHitGroup(content.GetPath("sounddata/relationships.hit"), content.GetPath("sounddata/relationships.evt"), content.GetPath("sounddata/relationships.hsm"));
            var tsoep5        = LoadHitGroup(content.GetPath("sounddata/tsoep5.hit"), content.GetPath("sounddata/tsoep5.evt"), content.GetPath("sounddata/tsoep5.hsm"));
            var tsoV2         = LoadHitGroup(content.GetPath("sounddata/tsov2.hit"), content.GetPath("sounddata/tsov2.evt"), null); //tsov2 has no hsm file
            var tsov3         = LoadHitGroup(content.GetPath("sounddata/tsov3.hit"), content.GetPath("sounddata/tsov3.evt"), content.GetPath("sounddata/tsov3.hsm"));
            var turkey        = LoadHitGroup(content.GetPath("sounddata/turkey.hit"), content.GetPath("sounddata/turkey.evt"), content.GetPath("sounddata/turkey.hsm"));

            RegisterEvents(newmain);
            RegisterEvents(relationships);
            RegisterEvents(tsoep5);
            RegisterEvents(tsoV2);
            RegisterEvents(tsov3);
            RegisterEvents(turkey);
        }
Exemple #10
0
        /// <summary>
        /// Gets a Hitlist from a DBPF using its InstanceID.
        /// </summary>
        /// <param name="InstanceID">The InstanceID of the Hitlist.</param>
        /// <param name="dbpf">The DBPF to search.</param>
        /// <returns>A Hitlist instance.</returns>
        private Hitlist GetHitlistFrom(uint InstanceID, DBPFFile dbpf)
        {
            var hit = dbpf.GetItemByID((ulong)DBPFTypeID.HIT + (((ulong)InstanceID) << 32));

            if (hit != null)
            {
                return(new Hitlist(hit));
            }

            return(null);
        }
Exemple #11
0
        /// <summary>
        /// Gets a track from a DBPF using its InstanceID.
        /// </summary>
        /// <param name="dbpf">The DBPF to search.</param>
        private void AddTracksFrom(DBPFFile dbpf)
        {
            var tracks = dbpf.GetItemsByType(DBPFTypeID.TRK);

            for (var i = 0; i < tracks.Count; i++)
            {
                var track  = new Track(tracks[i].Value);
                var realid = tracks[i].Key;
                TracksById.Add(realid, track);
                TracksByBackupId[track.TrackID] = track;
            }
        }
    void InitializeLot(Neighborhood nhood)
    {
        var lotFile = Path.Combine(nhood.nhoodFolder, "Lots/" + Path.GetFileName(nhood.nhoodFolder) + "_Lot" + lotNumber.ToString() + ".package");

        package = new DBPFFile(lotFile);
        var rcolFile = package.GetItemByFullID(Hash.TGIRHash(0xFF1FB89E, 0x3ADB7D39, 0xAC4F8687, Hash.GroupHash(Path.GetFileNameWithoutExtension(package.fname))));

        if (rcolFile != null)
        {
            imposterGMDC = new RCOLFile(new DBPFReference(rcolFile, package), true).dataBlocks[0] as GMDCDataBlock;
            foreach (var element in imposterGMDC.model.meshes)
            {
                element.RecalculateNormals();
            }
        }
    }
Exemple #13
0
 public static void ThreadedInit()
 {
     if (config.enable_mods)
     {
         var mods_folder = Path.Combine(config.user_dir, "Downloads");
         if (Directory.Exists(mods_folder))
         {
             DirectoryInfo modInfo = new DirectoryInfo(mods_folder);
             foreach (var file in modInfo.GetFiles("*.package", SearchOption.AllDirectories))
             {
                 DBPFFile.LoadResource(file.FullName, true);
             }
         }
     }
     LoadArchives(config.archives_main);
     LoadFinished = true;
 }
Exemple #14
0
        public DIRFile(DBPFFile file, byte[] bytes)
        {
            var stream = new MemoryStream(bytes);

            reader = IoBuffer.FromStream(stream, ByteOrder.LITTLE_ENDIAN);
            var count = 0;

            while (stream.Position < bytes.Length)
            {
                var entry = new DIREntry();

                entry.TypeID  = reader.ReadUInt32();
                entry.GroupID = reader.ReadUInt32();
                if (entry.GroupID == 0xFFFFFFFF && file.fname != "")
                {
                    entry.GroupID = Hash.GroupHash(Path.GetFileNameWithoutExtension(file.fname));
                }
                entry.InstanceID  = reader.ReadUInt32();
                entry.InstanceID2 = 0x0;

                if (file.IndexMinorVersion >= 2)
                {
                    entry.InstanceID2 = reader.ReadUInt32();
                }
                //m_EntryByID.Add((((ulong)entry.InstanceID) << 32) + (ulong)entry.InstanceID2 + (ulong)entry.TypeID, entry);

                /*
                 * var idEntry = new EntryRef(entry.InstanceID, entry.InstanceID2, entry.TypeID);
                 * if (!m_EntryByID.ContainsKey(idEntry))
                 *  m_EntryByID.Add(idEntry, entry);*/
                var idEntry2 = Hash.TGIRHash(entry.InstanceID, entry.InstanceID2, entry.TypeID, entry.GroupID);
                if (!m_EntryByFullID.ContainsKey(idEntry2))
                {
                    m_EntryByFullID.Add(idEntry2, entry);
                }
                entry.UncompressedFileSize = reader.ReadUInt32();
                count += 1;
            }
            reader.Dispose();
            stream.Dispose();
        }
Exemple #15
0
        /// <summary>
        /// Initializes the audio manager.
        /// </summary>
        public void Init()
        {
            this.Stations     = new List <AudioReference>();
            this.StationsById = new Dictionary <uint, AudioReference>();
            this.Modes        = new List <AudioReference>();

            var stationsRegEx = new Regex(@"music/stations/.*\.mp3");

            foreach (var file in ContentManager.AllFiles)
            {
                if (stationsRegEx.IsMatch(file))
                {
                    var reference = new AudioReference {
                        Type = AudioType.RADIO_STATION, FilePath = ContentManager.GetPath(file)
                    };
                    Stations.Add(reference);
                    var idString = Path.GetFileNameWithoutExtension(file);
                    idString = idString.Substring(idString.LastIndexOf("_") + 1);
                    var id = Convert.ToUInt32(idString, 16);
                    reference.ID = id;
                    StationsById.Add(id, reference);
                }
            }

            TSOAudio = new DBPFFile(ContentManager.GetPath("TSOAudio.dat"));
            tsov2    = new DBPFFile(ContentManager.GetPath("tsov2.dat"));
            Stings   = new DBPFFile(ContentManager.GetPath("Stings.dat"));
            EP5Samps = new DBPFFile(ContentManager.GetPath("EP5Samps.dat"));
            EP2      = new DBPFFile(ContentManager.GetPath("EP2.dat"));
            Hitlists = new DBPFFile(ContentManager.GetPath("HitListsTemp.dat"));

            SFXCache     = new Dictionary <uint, SoundEffect>();
            TracksById   = new Dictionary <uint, Track>();
            HitlistsById = new Dictionary <uint, Hitlist>();

            AddTracksFrom(TSOAudio);
        }
Exemple #16
0
    public Neighborhood(string folder)
    {
        nhoodFolder = Path.GetFullPath(folder).TrimEnd(Path.DirectorySeparatorChar);
        var packagePath = Path.Combine(folder, Path.GetFileName(nhoodFolder) + "_Neighborhood.package");

        package = new DBPFFile(packagePath);
        var stringsFile = package.GetItemByFullID(Hash.TGIRHash(0x00000001, 0x00000000, 0x43545353, package.groupID));

        if (stringsFile != null)
        {
            var ds = new STRFile(stringsFile);
            name = ds.GetString(0);
            desc = ds.GetString(1);
        }
        var pictureFile = Path.Combine(folder, Path.GetFileName(nhoodFolder) + "_Neighborhood.png");
        var hoodTexture = Environment.LoadUITexture(Hash.TGIRHash(0xCCC30155, 0x00000000, 0x856DDBAC, 0x499DB772));

        if (File.Exists(pictureFile))
        {
            hoodTexture = Environment.LoadUITexture(File.ReadAllBytes(pictureFile));
        }
        thumbnail = hoodTexture;
        largePic  = hoodTexture;
    }
        private void WriteAndCommit(string filename, Stream outfile, DBPFFile dbfile, Dictionary<DBPFReference, KeyValuePair<DBPFIndexEntry, byte[]>> toreplace, List<KeyValuePair<DBPFIndexEntry, byte[]>> toadd)
        {
            dbfile.Write(outfile, delegate(ref DBPFIndexEntry entry, ref byte[] data)
            {
                KeyValuePair<DBPFIndexEntry, byte[]> replacement;
                if (toreplace.TryGetValue(entry.Reference, out replacement))
                {
                    entry = replacement.Key;
                    data = replacement.Value;
                }
            }, toadd);

            foreach (DBPFReference commitref in toreplace.Keys)
            {
                StubbleSource source = new StubbleSource();
                source.SourceFile = filename;
                source.SourceTable = commitref;
                mData.CommitModifiedData((Languages)(commitref.Instance >> 56), source);
            }
            foreach (KeyValuePair<DBPFIndexEntry, byte[]> commitentry in toadd)
            {
                StubbleSource source = new StubbleSource();
                source.SourceFile = filename;
                source.SourceTable = commitentry.Key.Reference;
                mData.CommitModifiedData((Languages)(commitentry.Key.Reference.Instance >> 56), source);
            }
        }
        private void GatherSaveData(DBPFFile dbfile, Dictionary <DBPFReference, KeyValuePair <DBPFIndexEntry, byte[]> > toreplace, List <KeyValuePair <DBPFIndexEntry, byte[]> > toadd)
        {
            STBLWriter copysource = null;

            // Copy the reference language entries
            if (checkBox2.Checked)
            {
                copysource = new STBLWriter();
                foreach (KeyValuePair <UInt64, string> entry in mData.GetEntriesForLanguage((Languages)comboBox1.Items[comboBox1.SelectedIndex], STBLVault.StringSource.Modified | STBLVault.StringSource.Loaded))
                {
                    copysource.Add(entry.Key, entry.Value);
                }
            }

            for (int loop = 0; loop < (int)Languages.Language_Count; loop++)
            {
                // Skip languages there is nothing to write for
                if (!mData.HasEntriesForLanguage((Languages)loop, STBLVault.StringSource.Loaded | STBLVault.StringSource.Modified) &&
                    copysource == null)
                {
                    continue;
                }

                STBLWriter newentry;
                if (copysource != null)
                {
                    newentry = copysource.Copy();
                }
                else
                {
                    newentry = new STBLWriter();
                }
                newentry.Instance = mInstance;
                newentry.Language = (Languages)loop;

                // Overwrite or underwrite the user defined entries
                if (copysource != null && checkBox1.Checked)
                {
                    foreach (KeyValuePair <UInt64, string> entry in mData.GetEntriesForLanguage((Languages)loop, STBLVault.StringSource.Modified | STBLVault.StringSource.Loaded))
                    {
                        newentry.AddIfNotExists(entry.Key, entry.Value);
                    }
                }
                else
                {
                    foreach (KeyValuePair <UInt64, string> entry in mData.GetEntriesForLanguage((Languages)loop, STBLVault.StringSource.Modified | STBLVault.StringSource.Loaded))
                    {
                        newentry.Add(entry.Key, entry.Value);
                    }
                }

                // Load in the existing entry if requested
                if (radioButton2.Checked)
                {
                    DBPFReference oldref = new DBPFReference(0x220557DA, 0, mInstance | ((UInt64)loop << 56));
                    if (dbfile.Index.ContainsKey(oldref))
                    {
                        DBPFDataStream oldfile = dbfile.Open(oldref);
                        using (oldfile)
                        {
                            oldfile.GetData();
                            if (checkBox3.Checked)
                            {
                                // Merge overwriting old with new
                                foreach (KeyValuePair <UInt64, string> oldentry in STBLVault.GetDictionaryLoader(oldfile))
                                {
                                    newentry.AddIfNotExists(oldentry.Key, oldentry.Value);
                                }
                            }
                            else
                            {
                                // Merge overwriting new with old
                                foreach (KeyValuePair <UInt64, string> oldentry in STBLVault.GetDictionaryLoader(oldfile))
                                {
                                    newentry.Add(oldentry.Key, oldentry.Value);
                                }
                            }
                        }
                    }
                }

                // Create the STBL format data blob
                KeyValuePair <DBPFIndexEntry, byte[]> dbentry = newentry.Export();
                if (dbfile.Index.ContainsKey(dbentry.Key.Reference))
                {
                    toreplace[dbentry.Key.Reference] = dbentry;
                }
                else
                {
                    toadd.Add(dbentry);
                }
            }
        }
Exemple #19
0
        /// <summary>
        /// Initializes the audio manager.
        /// </summary>
        public void Init()
        {
            if (Initialized)
            {
                return;
            }
            this.Stations     = new List <AudioReference>();
            this.StationsById = new Dictionary <uint, AudioReference>();
            this.Modes        = new List <AudioReference>();

            var stationsRegEx = new Regex(@"music/stations/.*\.mp3");

            foreach (var file in ContentManager.AllFiles)
            {
                if (stationsRegEx.IsMatch(file))
                {
                    var reference = new AudioReference {
                        Type = AudioType.RADIO_STATION, FilePath = ContentManager.GetPath(file)
                    };
                    Stations.Add(reference);
                    var idString = Path.GetFileNameWithoutExtension(file);
                    idString = idString.Substring(idString.LastIndexOf("_") + 1);
                    var id = Convert.ToUInt32(idString, 16);
                    reference.ID = id;
                    StationsById.Add(id, reference);
                }
            }

            TSOAudio = new DBPFFile(ContentManager.GetPath("TSOAudio.dat"));
            tsov2    = new DBPFFile(ContentManager.GetPath("tsov2.dat"));
            Stings   = new DBPFFile(ContentManager.GetPath("Stings.dat"));
            EP5Samps = new DBPFFile(ContentManager.GetPath("EP5Samps.dat"));
            EP2      = new DBPFFile(ContentManager.GetPath("EP2.dat"));
            Hitlists = new DBPFFile(ContentManager.GetPath("HitListsTemp.dat"));

            SFXCache         = new Dictionary <uint, SoundEffect>();
            TracksById       = new Dictionary <uint, Track>();
            TracksByBackupId = new Dictionary <uint, Track>();
            HitlistsById     = new Dictionary <uint, Hitlist>();

            AddTracksFrom(TSOAudio);

            //load events
            _Events = new Dictionary <string, HITEventRegistration>();
            var content       = ContentManager;
            var newmain       = LoadHitGroup(content.GetPath("sounddata/newmain.hit"), content.GetPath("sounddata/eventlist.txt"), content.GetPath("sounddata/newmain.hsm"));
            var relationships = LoadHitGroup(content.GetPath("sounddata/relationships.hit"), content.GetPath("sounddata/relationships.evt"), content.GetPath("sounddata/relationships.hsm"));
            var tsoep5        = LoadHitGroup(content.GetPath("sounddata/tsoep5.hit"), content.GetPath("sounddata/tsoep5.evt"), content.GetPath("sounddata/tsoep5.hsm"));
            var tsoV2         = LoadHitGroup(content.GetPath("sounddata/tsov2.hit"), content.GetPath("sounddata/tsov2.evt"), null); //tsov2 has no hsm file
            var tsov3         = LoadHitGroup(content.GetPath("sounddata/tsov3.hit"), content.GetPath("sounddata/tsov3.evt"), content.GetPath("sounddata/tsov3.hsm"));
            var turkey        = LoadHitGroup(content.GetPath("sounddata/turkey.hit"), content.GetPath("sounddata/turkey.evt"), content.GetPath("sounddata/turkey.hsm"));

            RegisterEvents(newmain);
            RegisterEvents(relationships);
            RegisterEvents(tsoep5);
            RegisterEvents(tsoV2);
            RegisterEvents(tsov3);
            RegisterEvents(turkey);

            //register the .xa files over in the nightclub folders.
            var files = Directory.GetFiles(content.GetPath("sounddata/nightclubsounds/"));

            foreach (var file in files)
            {
                if (!file.EndsWith(".xa"))
                {
                    continue;
                }
                var  split = file.Split('_');
                uint id    = 0;
                try
                {
                    var endSplit = split[split.Length - 1];
                    id = Convert.ToUInt32("0x" + endSplit.Substring(0, endSplit.Length - 3), 16);
                }
                catch { continue; }

                NightclubSounds[id] = file;
            }

            Initialized = true;
        }
        public void Export(IWin32Window owner)
        {
            string origfilename = null;
            bool cleanup = false;
            try
            {
                try
                {
                    Stream outfile;
                    OpenOrCreate(mFilename, out origfilename, out cleanup, out outfile);

                    using (outfile)
                    {
                        DBPFFile dbfile;
                        if (origfilename == null)
                        {
                            dbfile = new DBPFFile();
                        }
                        else
                        {
                            dbfile = new DBPFFile(origfilename);
                        }

                        using (dbfile)
                        {
                            if (dbfile.IsProtected)
                            {
                                MessageBox.Show(owner, "Saving to protected DB files not allowed", "Save Error", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
                                return;
                            }

                            Dictionary<DBPFReference, KeyValuePair<DBPFIndexEntry, byte[]>> toreplace = new Dictionary<DBPFReference, KeyValuePair<DBPFIndexEntry, byte[]>>();
                            List<KeyValuePair<DBPFIndexEntry, byte[]>> toadd = new List<KeyValuePair<DBPFIndexEntry, byte[]>>();

                            GatherSaveData(dbfile, toreplace, toadd);

                            // Write the new file
                            WriteAndCommit(mFilename, outfile, dbfile, toreplace, toadd);
                        }
                    }
                    if (origfilename != null)
                        File.Delete(origfilename);
                    cleanup = false;
                }
                catch (Exception ex)
                {
                    MessageBox.Show(owner, string.Format("Error saving package:\n{0}", ex.Message), "Save Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                }
            }
            finally
            {
                PerformCleanup(mFilename, origfilename, cleanup);
            }
        }
        private void PerformLoad(bool asnewfile)
        {
            if (openFileDialog1.ShowDialog(this) != DialogResult.OK)
                return;

            int loaded = 0;
            bool cleared = !asnewfile;
            try
            {
                Stream stream = File.Open(openFileDialog1.FileName, FileMode.Open, FileAccess.Read);
                using (stream)
                {
                    byte[] header = new byte[4];
                    stream.Read(header, 0, 4);
                    stream.Position = 0;
                    if (Encoding.ASCII.GetString(header) == "DBPF")
                    {
                        DBPFFile file = new DBPFFile(stream);
                        using (file)
                        {
                            foreach (DBPFIndexEntry entry in file.Index)
                            {
                                if (entry.Reference.Type == 0x220557DA)
                                {
                                    StubbleSource source = new StubbleSource();
                                    source.SourceFile = openFileDialog1.FileName;
                                    source.SourceTable = entry.Reference;

                                    if (!cleared)
                                    {
                                        cleared = true;
                                        mStubbleEntries.ClearUserData();
                                        mCurExporter = null;
                                    }

                                    DBPFDataStream filedata = file.Open(entry.Reference);
                                    using (filedata)
                                    {
                                        // Force file-at-once read
                                        filedata.GetData();
                                        loaded += mStubbleEntries.LoadEntries(STBLVault.StringSource.Loaded, source,
                                            (Languages)(entry.Reference.Instance >> 56),
                                            STBLVault.OverwriteMode.PriorityOrEqual,
                                            STBLVault.GetDictionaryLoader(filedata));
                                    }
                                }
                            }
                            if (loaded == 0)
                            {
                                MessageBox.Show(this, "No STBL entries found", "Not Found", MessageBoxButtons.OK, MessageBoxIcon.Asterisk);
                                return;
                            }
                            if (!unmodifiedStringsToolStripMenuItem.Checked)
                                unmodifiedStringsToolStripMenuItem.Checked = true;
                            else
                                RepopulateTree();
                        }
                    }
                    else
                    {
                        ImportExport.ImportCSV importopts = new STBLBrowser.ImportExport.ImportCSV();
                        if (importopts.ShowDialog(this) == DialogResult.OK)
                        {
                            StubbleSource source = new StubbleSource();
                            source.SourceFile = openFileDialog1.FileName;
                            loaded += mStubbleEntries.LoadEntries(STBLVault.StringSource.Loaded, source,
                                importopts.ImportLanguage,
                                STBLVault.OverwriteMode.All,
                                importopts.ImportStrings(this, stream));
                            if (loaded == 0)
                            {
                                MessageBox.Show(this, "No STBL entries found", "Not Found", MessageBoxButtons.OK, MessageBoxIcon.Asterisk);
                                return;
                            }
                            STBLVault.SyncKeyNameMap();
                            if (!unmodifiedStringsToolStripMenuItem.Checked)
                                unmodifiedStringsToolStripMenuItem.Checked = true;
                            else
                                RepopulateTree();
                        }
                    }
                }
                if (asnewfile)
                    Text = "Stubble String Table Editor - " + openFileDialog1.FileName;
            }
            catch (Exception ex)
            {
                MessageBox.Show(this, string.Format("Error reading file: {0}", ex.Message), "File Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }
        public bool Export(IWin32Window owner, string filename)
        {
            if (comboBox1.Items.Count == 0)
            {
                MessageBox.Show(owner, "No loaded or modified data to save", "No data", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
                return(false);
            }
            AnalyzePackage();
            if (mInstance != UInt64.MaxValue)
            {
                textBox1.Text     = mInstance.ToString("X14");
                checkBox5.Checked = true;
            }
            else
            {
                checkBox5.Checked = false;
            }

            UInt64 existing;

            string origfilename = null;
            bool   cleanup      = false;

            try
            {
                try
                {
                    Stream outfile;
                    OpenOrCreate(filename, out origfilename, out cleanup, out outfile);

                    using (outfile)
                    {
                        DBPFFile dbfile;
                        if (origfilename == null)
                        {
                            dbfile = new DBPFFile();
                        }
                        else
                        {
                            dbfile = new DBPFFile(origfilename);
                        }

                        using (dbfile)
                        {
                            if (dbfile.IsProtected)
                            {
                                MessageBox.Show(owner, "Saving to protected DB files not allowed", "Save Error", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
                                return(false);
                            }
                            // Find any existing STBL instances
                            existing = UInt64.MaxValue;
                            foreach (DBPFIndexEntry entry in dbfile.Index)
                            {
                                if (entry.Reference.Type == 0x220557DA)
                                {
                                    if (existing == UInt64.MaxValue || (UInt32)entry.Reference.Instance < (UInt32)existing)
                                    {
                                        existing = entry.Reference.Instance & ~(0xFFUL << 56);
                                    }
                                }
                            }

                            // Disable options that make no sense if there is no entry to replace
                            if (existing != UInt64.MaxValue)
                            {
                                radioButton2.Checked = true;
                                radioButton2.Enabled = true;
                                radioButton3.Enabled = true;
                            }
                            else
                            {
                                radioButton1.Checked = true;
                                radioButton2.Enabled = false;
                                radioButton3.Enabled = false;
                            }

                            if (ShowDialog(owner) != DialogResult.OK)
                            {
                                return(false);
                            }

                            // Figure out what instance to write
                            mInstance = 0;
                            if (radioButton1.Checked)
                            {
                                // Check if instance specified
                                if (!(checkBox5.Checked && UInt64.TryParse(textBox1.Text, out mInstance)))
                                {
                                    // Generate a new instance, making the priority close to the high end of usable values
                                    byte[] ranval = Guid.NewGuid().ToByteArray();
                                    mInstance = (UInt64)(BitConverter.ToUInt32(ranval, 1) & 0xFFFFFF) << 32;
                                    UInt64 priority = mHighestPriority;
                                    if (priority == UInt32.MaxValue)
                                    {
                                        priority++;
                                    }
                                    priority /= 8;
                                    if (priority == 0)
                                    {
                                        priority = 1;
                                    }
                                    UInt64 chosenpriority = BitConverter.ToUInt64(ranval, 6) % priority + priority * 7;
                                    mInstance |= chosenpriority;
                                }
                            }
                            else
                            {
                                // Replace an existing entry
                                mInstance = existing;
                            }

                            Dictionary <DBPFReference, KeyValuePair <DBPFIndexEntry, byte[]> > toreplace = new Dictionary <DBPFReference, KeyValuePair <DBPFIndexEntry, byte[]> >();
                            List <KeyValuePair <DBPFIndexEntry, byte[]> > toadd = new List <KeyValuePair <DBPFIndexEntry, byte[]> >();

                            GatherSaveData(dbfile, toreplace, toadd);

                            // Write the new file
                            WriteAndCommit(filename, outfile, dbfile, toreplace, toadd);
                        }
                    }
                    if (origfilename != null)
                    {
                        File.Delete(origfilename);
                    }
                    cleanup   = false;
                    mFilename = filename;
                    return(true);
                }
                catch (Exception ex)
                {
                    MessageBox.Show(owner, string.Format("Error saving package:\n{0}", ex.Message), "Save Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                }
            }
            finally
            {
                PerformCleanup(filename, origfilename, cleanup);
            }
            return(false);
        }
        private void GatherSaveData(DBPFFile dbfile, Dictionary<DBPFReference, KeyValuePair<DBPFIndexEntry, byte[]>> toreplace, List<KeyValuePair<DBPFIndexEntry, byte[]>> toadd)
        {
            STBLWriter copysource = null;
            // Copy the reference language entries
            if (checkBox2.Checked)
            {
                copysource = new STBLWriter();
                foreach (KeyValuePair<UInt64, string> entry in mData.GetEntriesForLanguage((Languages)comboBox1.Items[comboBox1.SelectedIndex], STBLVault.StringSource.Modified | STBLVault.StringSource.Loaded))
                {
                    copysource.Add(entry.Key, entry.Value);
                }
            }

            for (int loop = 0; loop < (int)Languages.Language_Count; loop++)
            {
                // Skip languages there is nothing to write for
                if (!mData.HasEntriesForLanguage((Languages)loop, STBLVault.StringSource.Loaded | STBLVault.StringSource.Modified)
                    && copysource == null)
                    continue;

                STBLWriter newentry;
                if (copysource != null)
                    newentry = copysource.Copy();
                else
                    newentry = new STBLWriter();
                newentry.Instance = mInstance;
                newentry.Language = (Languages)loop;

                // Overwrite or underwrite the user defined entries
                if (copysource != null && checkBox1.Checked)
                    foreach (KeyValuePair<UInt64, string> entry in mData.GetEntriesForLanguage((Languages)loop, STBLVault.StringSource.Modified | STBLVault.StringSource.Loaded))
                        newentry.AddIfNotExists(entry.Key, entry.Value);
                else
                    foreach (KeyValuePair<UInt64, string> entry in mData.GetEntriesForLanguage((Languages)loop, STBLVault.StringSource.Modified | STBLVault.StringSource.Loaded))
                        newentry.Add(entry.Key, entry.Value);

                // Load in the existing entry if requested
                if (radioButton2.Checked)
                {
                    DBPFReference oldref = new DBPFReference(0x220557DA, 0, mInstance | ((UInt64)loop << 56));
                    if (dbfile.Index.ContainsKey(oldref))
                    {
                        DBPFDataStream oldfile = dbfile.Open(oldref);
                        using (oldfile)
                        {
                            oldfile.GetData();
                            if (checkBox3.Checked)
                            {
                                // Merge overwriting old with new
                                foreach (KeyValuePair<UInt64, string> oldentry in STBLVault.GetDictionaryLoader(oldfile))
                                {
                                    newentry.AddIfNotExists(oldentry.Key, oldentry.Value);
                                }
                            }
                            else
                            {
                                // Merge overwriting new with old
                                foreach (KeyValuePair<UInt64, string> oldentry in STBLVault.GetDictionaryLoader(oldfile))
                                {
                                    newentry.Add(oldentry.Key, oldentry.Value);
                                }
                            }
                        }
                    }
                }

                // Create the STBL format data blob
                KeyValuePair<DBPFIndexEntry, byte[]> dbentry = newentry.Export();
                if (dbfile.Index.ContainsKey(dbentry.Key.Reference))
                    toreplace[dbentry.Key.Reference] = dbentry;
                else
                    toadd.Add(dbentry);
            }
        }
Exemple #24
0
        void ThreadedStuff()
        {
            failed = false;
            trace  = "";
            errors = new List <PackageError>();
            var  pendingPackages   = new List <PackageToWrite>();
            var  currentPack       = new PackageToWrite();
            long currentPackSize   = 0;
            uint currentFileAmount = 0;

            pendingPackages.Add(currentPack);
            //var dirInfo = new DirectoryInfo(downloadsDir);
            var packages       = new List <DBPFFile>();
            var entryAmount    = 0;
            var gotCompression = false;

            fileAmount     = 0;
            currentFile    = 0;
            downloadsDir   = downloadsDir.Replace("/", "\\");
            startedWriting = false;
            var packageCount = 0; //For logging purposes

            foreach (var element in Delimon.Win32.IO.Directory.GetFiles(downloadsDir, "*.package", Delimon.Win32.IO.SearchOption.AllDirectories))
            {
                try
                {
                    var pack = new DBPFFile(element);
                    currentPackSize   += new Delimon.Win32.IO.FileInfo(element).Length;
                    currentFileAmount += pack.NumEntries;
                    if ((currentPackSize >= packageMaxSize && packageMaxSize != 0) || (currentFileAmount >= packageMaxFileAmount && packageMaxFileAmount != 0))
                    {
                        currentPack       = new PackageToWrite();
                        currentPackSize   = 0;
                        currentFileAmount = 0;
                        pendingPackages.Add(currentPack);
                    }
                    fileAmount += pack.NumEntries;
                    if (pack.hasCompression)
                    {
                        gotCompression       = true;
                        currentPack.compress = true;
                        fileAmount          -= 1;
                    }
                    entryAmount += (int)pack.NumEntries;
                    //packages.Add(pack);
                    currentPack.packages.Add(pack);
                    packageCount += 1;
                }
                catch (Exception e)
                {
                    var err = new PackageError()
                    {
                        file  = element,
                        trace = e.ToString()
                    };
                    errors.Add(err);
                    //MessageBox.Show("There was an error reading package " + element + "." + Environment.NewLine + e.ToString(), "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                }
            }
            if (fileAmount == 0)
            {
                MessageBox.Show("There are no packages to merge in here, or they're all empty!", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                isFinished = true;
                return;
            }
            fileAmount    *= 2;
            startedWriting = true;
            byte[] dirfil = null;
            try
            {
                for (var i = 0; i < pendingPackages.Count; i++)
                {
                    var packToWrite = pendingPackages[i];
                    var dirStream   = new MemoryStream();
                    var dirWriter   = new BinaryWriter(dirStream);
                    foreach (var packa in packToWrite.packages)
                    {
                        foreach (var element in packa.m_EntryByID)
                        {
                            if (element.Value.TypeID != 0xE86B1EEF && element.Value.uncompressedSize != 0)
                            {
                                //fileAmount += 1;
                                //TypeID
                                dirWriter.Write(element.Value.TypeID);
                                //GroupID
                                dirWriter.Write(element.Value.GroupID);
                                //InstanceID
                                dirWriter.Write(element.Value.InstanceID);
                                //ResourceID
                                dirWriter.Write(element.Value.InstanceID2);
                                //UncompressedSize
                                dirWriter.Write(element.Value.uncompressedSize);
                            }
                        }
                    }
                    dirfil = dirStream.ToArray();
                    dirWriter.Dispose();
                    dirStream.Dispose();
                    var fname = Path.Combine(Path.GetDirectoryName(target), Path.GetFileNameWithoutExtension(target) + i.ToString() + ".package");
                    packToWrite.name = fname;
                    var mStream = new FileStream(fname, FileMode.Create);
                    var mWriter = new BinaryWriter(mStream);
                    //HeeeADER
                    mWriter.Write(new char[] { 'D', 'B', 'P', 'F' });
                    //major version
                    mWriter.Write((int)1);
                    //minor version
                    mWriter.Write((int)2);
                    mWriter.Write(new byte[12]);
                    //Date stuff
                    mWriter.Write((int)0);
                    mWriter.Write((int)0);
                    //Index major
                    mWriter.Write((int)7);
                    //Num entries
                    var entryAmountOffset = mStream.Position;
                    mWriter.Write((int)0);
                    //Index offset
                    var indexOff = mStream.Position;
                    //Placeholder
                    mWriter.Write((int)0);
                    //Index size
                    var indexSize = mStream.Position;
                    //Placeholder
                    mWriter.Write((int)0);

                    //Trash Entry Stuff
                    mWriter.Write((int)0);
                    mWriter.Write((int)0);
                    mWriter.Write((int)0);

                    //Index Minor Ver
                    mWriter.Write((int)2);
                    //Padding
                    mWriter.Write(new byte[32]);

                    var lastPos = mStream.Position;
                    mStream.Position = indexOff;
                    mWriter.Write((int)lastPos);
                    mStream.Position = lastPos;
                    var  entryAmount2 = 0;
                    var  indeOf       = mStream.Position;
                    long dirFilOffset = 0;
                    if (packToWrite.compress)
                    {
                        currentFile += 1;
                        //TypeID
                        mWriter.Write(0xE86B1EEF);
                        //GroupID
                        mWriter.Write(0xE86B1EEF);
                        //InstanceID
                        mWriter.Write(0x286B1F03);
                        //ResourceID
                        mWriter.Write(0x00000000);
                        //File Offset
                        dirFilOffset = mStream.Position;
                        mWriter.Write((int)0);
                        //File Size
                        mWriter.Write(dirfil.Length);
                        entryAmount2 += 1;
                    }
                    foreach (var packa in packToWrite.packages)
                    {
                        foreach (var element in packa.m_EntryByID)
                        {
                            if (element.Value.TypeID != 0xE86B1EEF)
                            {
                                currentFile += 1;
                                //TypeID
                                mWriter.Write(element.Value.TypeID);
                                //GroupID
                                mWriter.Write(element.Value.GroupID);
                                //InstanceID
                                mWriter.Write(element.Value.InstanceID);
                                //ResourceID
                                mWriter.Write(element.Value.InstanceID2);
                                //File Offset
                                element.Value.writeOff = mStream.Position;
                                mWriter.Write((int)0);
                                //File Size
                                mWriter.Write(element.Value.FileSize);
                                entryAmount2 += 1;
                            }
                        }
                    }
                    lastPos          = mStream.Position;
                    mStream.Position = entryAmountOffset;
                    mWriter.Write(entryAmount2);
                    var siz = lastPos - indeOf;
                    mStream.Position = indexOff;
                    mWriter.Write(indeOf);
                    mStream.Position = indexSize;
                    mWriter.Write(siz);
                    mStream.Position = lastPos;
                    if (packToWrite.compress)
                    {
                        lastPos          = mStream.Position;
                        mStream.Position = dirFilOffset;
                        mWriter.Write((int)lastPos);
                        mStream.Position = lastPos;
                        mWriter.Write(dirfil);
                    }
                    foreach (var packa in packToWrite.packages)
                    {
                        foreach (var element in packa.m_EntryByID)
                        {
                            System.GC.Collect(); // Just in case?
                            if (element.Value.TypeID != 0xE86B1EEF)
                            {
                                currentFile     += 1;
                                lastPos          = mStream.Position;
                                mStream.Position = element.Value.writeOff;
                                mWriter.Write((int)lastPos);
                                mStream.Position = lastPos;
                                var ent = packa.GetEntry(element.Value);
                                mWriter.Write(ent);
                            }
                        }
                    }
                    mWriter.Dispose();
                    mStream.Dispose();
                }
            }
            catch (Exception e)
            {
                MessageBox.Show("There was an error writing the merged packages:" + Environment.NewLine + e.ToString(), "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                failed = true;
                trace  = e.ToString();
            }
            var logName = Path.Combine(Path.GetDirectoryName(target), "CCMerger.log");

            using (StreamWriter logStream = new StreamWriter(logName))
            {
                logStream.WriteLine("CCMerger log - version " + Program.version);
                logStream.WriteLine();
                logStream.WriteLine("[Settings Used]");
                logStream.WriteLine("Max files per package: " + packFiles.Value);
                logStream.WriteLine("Max package size: " + packSize.Value + " mb");
                logStream.WriteLine();
                logStream.WriteLine("[Results]");
                logStream.WriteLine("Merged " + packageCount + " packages containing " + fileAmount + " files into " + pendingPackages.Count + " packages.");
                logStream.WriteLine();
                logStream.WriteLine("[Errors]");
                logStream.WriteLine(errors.Count + " packages failed to merge.");
                foreach (var element in errors)
                {
                    logStream.WriteLine("Package name: " + element.file);
                    logStream.WriteLine(element.trace);
                }
                if (failed)
                {
                    logStream.WriteLine("Failed to merge packages :(");
                    logStream.WriteLine(trace);
                }
                else
                {
                    logStream.WriteLine("Packages were merged succesfully :)");
                }
            }
            if (logBox.Checked)
            {
                foreach (var element in pendingPackages)
                {
                    var simpleName = Path.GetFileName(element.name);
                    var fname      = Path.Combine(Path.GetDirectoryName(element.name), Path.GetFileNameWithoutExtension(element.name) + ".txt");
                    using (StreamWriter logStream = new StreamWriter(fname))
                    {
                        logStream.WriteLine("Contents of " + simpleName + ":");
                        logStream.WriteLine();
                        foreach (var packs in element.packages)
                        {
                            logStream.WriteLine(Path.GetFileName(packs.fname));
                        }
                        logStream.WriteLine();
                    }
                }
            }
            isFinished = true;
        }
        public bool Export(IWin32Window owner, string filename)
        {
            if (comboBox1.Items.Count == 0)
            {
                MessageBox.Show(owner, "No loaded or modified data to save", "No data", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
                return false;
            }
            AnalyzePackage();
            if (mInstance != UInt64.MaxValue)
            {
                textBox1.Text = mInstance.ToString("X14");
                checkBox5.Checked = true;
            }
            else
                checkBox5.Checked = false;

            UInt64 existing;

            string origfilename = null;
            bool cleanup = false;
            try
            {
                try
                {
                    Stream outfile;
                    OpenOrCreate(filename, out origfilename, out cleanup, out outfile);

                    using (outfile)
                    {
                        DBPFFile dbfile;
                        if (origfilename == null)
                        {
                            dbfile = new DBPFFile();
                        }
                        else
                        {
                            dbfile = new DBPFFile(origfilename);
                        }

                        using (dbfile)
                        {
                            if (dbfile.IsProtected)
                            {
                                MessageBox.Show(owner, "Saving to protected DB files not allowed", "Save Error", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
                                return false;
                            }
                            // Find any existing STBL instances
                            existing = UInt64.MaxValue;
                            foreach (DBPFIndexEntry entry in dbfile.Index)
                            {
                                if (entry.Reference.Type == 0x220557DA)
                                {
                                    if (existing == UInt64.MaxValue || (UInt32)entry.Reference.Instance < (UInt32)existing)
                                        existing = entry.Reference.Instance & ~(0xFFUL << 56);
                                }
                            }

                            // Disable options that make no sense if there is no entry to replace
                            if (existing != UInt64.MaxValue)
                            {
                                radioButton2.Checked = true;
                                radioButton2.Enabled = true;
                                radioButton3.Enabled = true;
                            }
                            else
                            {
                                radioButton1.Checked = true;
                                radioButton2.Enabled = false;
                                radioButton3.Enabled = false;
                            }

                            if (ShowDialog(owner) != DialogResult.OK)
                                return false;

                            // Figure out what instance to write
                            mInstance = 0;
                            if (radioButton1.Checked)
                            {
                                // Check if instance specified
                                if (!(checkBox5.Checked && UInt64.TryParse(textBox1.Text, out mInstance)))
                                {
                                    // Generate a new instance, making the priority close to the high end of usable values
                                    byte[] ranval = Guid.NewGuid().ToByteArray();
                                    mInstance = (UInt64)(BitConverter.ToUInt32(ranval, 1) & 0xFFFFFF) << 32;
                                    UInt64 priority = mHighestPriority;
                                    if (priority == UInt32.MaxValue)
                                        priority++;
                                    priority /= 8;
                                    if (priority == 0)
                                        priority = 1;
                                    UInt64 chosenpriority = BitConverter.ToUInt64(ranval, 6) % priority + priority * 7;
                                    mInstance |= chosenpriority;
                                }
                            }
                            else
                                // Replace an existing entry
                                mInstance = existing;

                            Dictionary<DBPFReference, KeyValuePair<DBPFIndexEntry, byte[]>> toreplace = new Dictionary<DBPFReference, KeyValuePair<DBPFIndexEntry, byte[]>>();
                            List<KeyValuePair<DBPFIndexEntry, byte[]>> toadd = new List<KeyValuePair<DBPFIndexEntry, byte[]>>();

                            GatherSaveData(dbfile, toreplace, toadd);

                            // Write the new file
                            WriteAndCommit(filename, outfile, dbfile, toreplace, toadd);
                        }
                    }
                    if (origfilename != null)
                        File.Delete(origfilename);
                    cleanup = false;
                    mFilename = filename;
                    return true;
                }
                catch (Exception ex)
                {
                    MessageBox.Show(owner, string.Format("Error saving package:\n{0}", ex.Message), "Save Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                }
            }
            finally
            {
                PerformCleanup(filename, origfilename, cleanup);
            }
            return false;
        }