コード例 #1
0
        public void Reload(LevelSettings settings, IDialogHandler progressReporter = null)
        {
            if (string.IsNullOrEmpty(Path))
            {
                Sounds        = null;
                LoadException = new Exception("Path is empty.");
                return;
            }

            // Load the catalog
            try
            {
                var path = settings.MakeAbsolute(Path);
                if (File.Exists(path))
                {
                    WadSounds newSounds = WadSounds.ReadFromFile(path);
                    Sounds        = newSounds;
                    LoadException = null;
                }
                else
                {
                    LoadException = new Exception("File not found: " + path);
                }
            }
            catch (Exception exc)
            {
                logger.Warn(exc, "Unable to load catalog '" + Path + "'.");
                Sounds        = null;
                LoadException = exc;
            }
        }
コード例 #2
0
        private bool OpenArchive(string filename = null)
        {
            CheckForSavedChanges();

            if (filename == null)
            {
                filename = LevelFileDialog.BrowseFile(this, null, _configuration.SoundTool_LastCatalogPath, "Select archive to open",
                                                      WadSounds.FormatExtensions, null,
                                                      false);
            }

            if (filename == null || !File.Exists(filename))
            {
                return(false);
            }

            // Read the sounds archive in XML or TXT format
            var sounds = WadSounds.ReadFromFile(filename);

            if (sounds == null)
            {
                return(false);
            }

            // File read correctly, save catalog path to recent
            _configuration.SoundTool_LastCatalogPath = filename;

            dgvSoundInfos.Rows.Clear();

            // Fill the grid
            sounds.SoundInfos.Sort((a, b) => a.Id.CompareTo(b.Id));
            foreach (var soundInfo in sounds.SoundInfos)
            {
                dgvSoundInfos.Rows.Add(soundInfo.Id.ToString().PadLeft(4, '0'), soundInfo.Name);
                dgvSoundInfos.Rows[dgvSoundInfos.Rows.Count - 1].Tag = soundInfo;
            }

            SelectSoundInfo();

            // Decide on saved flag based on file format.
            // If TXT was loaded (i.e. conversion was made), mark the file as unsaved.
            var extension = Path.GetExtension(filename);

            if (extension == ".xml")
            {
                _currentArchive = filename;
                Saved           = true;
            }
            else
            {
                _currentArchive = null;
                Saved           = false;
            }
            return(true);
        }
コード例 #3
0
        private void Prj2SoundsConversionDialog_Load(object sender, EventArgs e)
        {
            // Try to load default Sounds.xml
            if (File.Exists("Catalogs\\Sounds.tr4.xml"))
            {
                string filename = Path.GetDirectoryName(Application.ExecutablePath) + "\\Catalogs\\Sounds.tr4.xml";
                var    sounds   = WadSounds.ReadFromFile(filename);
                if (sounds != null)
                {
                    Sounds = sounds;
                    tbSoundsCatalogPath.Text = filename;
                }
            }

            // Add rows
            ReloadSoundInfos();
        }
コード例 #4
0
        private void butSearchSoundsCatalogPath_Click(object sender, EventArgs e)
        {
            string result = LevelFileDialog.BrowseFile(this, "Select sound catalog to import",
                                                       LevelSettings.FileFormatsSoundsCatalogs,
                                                       false);

            if (result != null)
            {
                var sounds = WadSounds.ReadFromFile(result);
                if (sounds == null)
                {
                    return;
                }
                Sounds = sounds;
                tbSoundsCatalogPath.Text = result;
            }
        }
コード例 #5
0
        public static Wad2 ConvertTr4Wad(Tr4Wad oldWad, IDialogHandler progressReporter)
        {
            logger.Info("Converting TR4 WAD to Wad2");

            var wad = new Wad2()
            {
                SoundSystem = SoundSystem.Xml, GameVersion = TRVersion.Game.TR4
            };

            // Convert all textures
            Dictionary <int, WadTexture> textures = ConvertTr4TexturesToWadTexture(oldWad, wad);

            logger.Info("Textures read.");

            // Convert sounds
            var sfxPath = Path.GetDirectoryName(oldWad.FileName) + "\\" + Path.GetFileNameWithoutExtension(oldWad.FileName) + ".sfx";

            if (File.Exists(sfxPath))
            {
                wad.Sounds = WadSounds.ReadFromFile(sfxPath);
                logger.Info("Sounds read.");
            }

            // Convert moveables
            for (int i = 0; i < oldWad.Moveables.Count; i++)
            {
                ConvertTr4MoveableToWadMoveable(wad, oldWad, i, textures);
            }
            logger.Info("Moveables read.");

            // Convert statics
            for (int i = 0; i < oldWad.Statics.Count; i++)
            {
                ConvertTr4StaticMeshToWadStatic(wad, oldWad, i, textures);
            }
            logger.Info("Statics read.");

            // Convert sprites
            ConvertTr4Sprites(wad, oldWad);
            logger.Info("Sprites read.");

            return(wad);
        }
コード例 #6
0
        private void SaveArchive(string filename = null)
        {
            if (filename == null)
            {
                filename = LevelFileDialog.BrowseFile(this, "Save sound catalog to XML",
                                                      LevelSettings.FileFormatsSoundsXmlFiles,
                                                      true);
            }
            if (filename == null)
            {
                return;
            }

            Sounds.SoundInfos.Sort((a, b) => a.Id.CompareTo(b.Id));
            WadSounds.SaveToXml(filename, Sounds);

            _currentArchive = filename;
            Saved           = true;
        }
コード例 #7
0
        private bool AddSampleToList(string name)
        {
            var  path     = string.Empty;
            bool notFound = false;

            if (_referenceLevel != null)
            {
                var foundPath = WadSounds.TryGetSamplePath(_referenceLevel.Settings, name);
                notFound = string.IsNullOrEmpty(foundPath);
                path     = notFound ? "[ not found in any reference project sample paths ]" : foundPath;
            }

            dgvSamples.Rows.Add(name, path);

            // Highlight row if sample is missing

            if (notFound)
            {
                dgvSamples.Rows[dgvSamples.Rows.Count - 1].DefaultCellStyle.BackColor = dgvSamples.BackColor.MixWith(Color.DarkRed, 0.55);
            }

            return(!notFound);
        }
コード例 #8
0
        public static bool ConvertWad2ToNewSoundFormat(string src, string dest)
        {
            /* PROCEDURE:
             * 1. Collect all sounds from Wad2
             * 2. Initialise the list of SoundInfoConversionRow, getting ID from TrCatalog
             * 3. Show the dialog to the user. Here he can load an additional catalog if he changed sounds via TRLE tools.
             *    He can also choose which sounds to export to Xml and if export also samples.
             * 4. Assign new IDs to sound infos
             * 5. Remap sounds in animcommands
             * 6. Optionally export samples if needed and bind them to sound infos
             * 7. Save Wad2 + Xml (if sounds are present)
             */

            try
            {
                // Load Wad2
                Wad2 wad = Wad2Loader.LoadFromFile(src, false);

                // Check if the Wad2 needs to be converted
                if (wad.SoundSystem != SoundSystem.Dynamic)
                {
                    return(true);
                }

                // Now collect all sound infos from obsolete lists and build a new list
                var soundInfos = wad.AllLoadedSoundInfos.Values.ToList();

                // Loop through each sound info and try to get the classic Id from TrCatalog.xml
                var conversionList = new List <SoundInfoConversionRow>();
                foreach (var soundInfo in soundInfos)
                {
                    var row = new SoundInfoConversionRow(soundInfo, soundInfo.Name);

                    // If user has changed name, result will be -1 and the user will need to manually set the new sound id
                    row.NewId = TrCatalog.TryGetSoundInfoIdByDescription(wad.GameVersion, soundInfo.Name);
                    if (row.NewId != -1)
                    {
                        row.NewName = TrCatalog.GetOriginalSoundName(wad.GameVersion, (uint)row.NewId);
                    }

                    conversionList.Add(row);
                }

                // Now we'll show a dialog with all conversion rows and the user will need to make some choices
                WadSounds sounds = null;
                using (var form = new Wad2SoundsConversionDialog(wad.GameVersion, conversionList))
                {
                    if (form.ShowDialog() == DialogResult.Cancel)
                    {
                        return(false);
                    }

                    // If the user has loaded a custom catalog, let's get a pointer to it
                    if (form.Sounds != null)
                    {
                        sounds = form.Sounds;
                    }
                }

                // Assign new Id and name
                foreach (var row in conversionList)
                {
                    row.SoundInfo.Id   = row.NewId;
                    row.SoundInfo.Name = row.NewName;
                }

                // Remap all sounds in animcommands
                foreach (var row in conversionList)
                {
                    if (row.NewId != -1)
                    {
                        foreach (var moveable in wad.Moveables)
                        {
                            foreach (var animation in moveable.Value.Animations)
                            {
                                foreach (var cmd in animation.AnimCommands)
                                {
                                    if (cmd.SoundInfoObsolete != null && cmd.SoundInfoObsolete == row.SoundInfo)
                                    {
                                        cmd.Parameter2        = (short)((cmd.Parameter2 & 0xc000) | row.NewId);
                                        cmd.SoundInfoObsolete = null;
                                    }
                                }
                            }
                        }
                    }
                }

                // Bind samples (only if additional catalog was loaded, TrCatalog has not samples names)
                if (sounds != null)
                {
                    foreach (var row in conversionList)
                    {
                        if (row.SaveToXml)
                        {
                            if (row.ExportSamples)
                            {
                                // We export samples only if user has marked both Export to Xml and Export samples checkboxes
                                var samples = new List <string>();
                                foreach (var sample in row.SoundInfo.Samples)
                                {
                                    if (sample.IsLoaded)
                                    {
                                        // If sample is valid, export the .WAV file to the same directory of Wad2
                                        string sampleName = row.NewName.ToLower() + "_" + row.SoundInfo.Samples.IndexOf(sample) + ".wav";
                                        samples.Add(sampleName);
                                        File.WriteAllBytes(Path.GetDirectoryName(dest) + "\\" + sampleName, sample.Data);
                                    }
                                }

                                // Assign new samples names
                                row.SoundInfo.Samples.Clear();
                                foreach (var sample in samples)
                                {
                                    row.SoundInfo.Samples.Add(new WadSample(sample));
                                }
                            }
                            else
                            {
                                // If samples count is the same then use samples from catalog
                                var refInfo = sounds.TryGetSoundInfo(row.NewId);

                                if (refInfo != null && row.SoundInfo.Samples.Count == refInfo.Samples.Count)
                                {
                                    row.SoundInfo.Samples.Clear();
                                    row.SoundInfo.Samples.AddRange(refInfo.Samples);
                                }
                                else
                                {
                                    row.SoundInfo.Samples.Clear();
                                }
                            }
                        }
                    }
                }

                // Create the new sounds archive
                foreach (var row in conversionList)
                {
                    if (row.SaveToXml)
                    {
                        wad.Sounds.SoundInfos.Add(row.SoundInfo);
                    }
                }

                // Sort sound infos
                wad.Sounds.SoundInfos.Sort((a, b) => a.Id.CompareTo(b.Id));

                // Make a backup copy
                if (src == dest)
                {
                    int    index          = 0;
                    string backupFilename = "";
                    while (true)
                    {
                        backupFilename = dest + "." + index + ".bak";
                        if (!File.Exists(backupFilename))
                        {
                            break;
                        }
                        index++;
                    }

                    File.Copy(src, backupFilename, true);
                }

                // Save Wad2 with Xml sounds
                wad.SoundSystem = SoundSystem.Xml;
                Wad2Writer.SaveToFile(wad, dest);

                // Finished!
                return(true);
            }
            catch (Exception e)
            {
                return(false);
            }
        }
コード例 #9
0
        public static bool ConvertPrj2ToNewSoundFormat(Level level, string src, string dest, string soundsCatalog, bool save)
        {
            /* PROCEDURE:
             * 1. Collect all sound sources of level: if embedded sound info is null, then it's a sound source
             *    that is referencing a Wad file and we should just remap it, otherwise it's a custom sound source
             *    created inside Tomb Editor and we must export it to Xml and we must export samples too
             * 2. Try to guess the ID for Wad sounds and generate instead a new ID above 602 for custom sounds
             *    (ID = 602 is the start of TR1 area of extended soundmap of TRNG and it should be rarely used)
             * 3. Show the dialog to the user. Here he can load an additional catalog if he changed sounds via TRLE tools
             * 4. Assign new IDs and new names to sound infos
             * 5. Remap sound sources
             * 6. Export samples if needed
             * 7. Save Prj2 + Xml if custom sounds are present
             */

            try
            {
                // Check for sound system
                if (level.Settings.SoundSystem == SoundSystem.Xml)
                {
                    return(true);
                }

                // Infer the wad version from level version
                TRVersion.Game version = level.Settings.GameVersion.Native();

                // Collect all sounds to remap
                var conversionList = new List <SoundInfoConversionRow>();

                // We start from sound id = 602 which is the TR1 sound area of TRNG extended soundmap.
                // This area is reserved for TR1 enemies and so it *** should *** be used rarely
                int lastSoundId = 602;

                foreach (var room in level.Rooms)
                {
                    if (room != null)
                    {
                        foreach (var obj in room.Objects)
                        {
                            if (obj is SoundSourceInstance)
                            {
                                SoundSourceInstance soundSource = obj as SoundSourceInstance;

                                if (soundSource.WadReferencedSoundName != null && soundSource.WadReferencedSoundName != "")
                                {
                                    if (!conversionList.Select(f => f.OldName).Contains(soundSource.WadReferencedSoundName))
                                    {
                                        // First try to get sound name from TrCatalog
                                        int newId = TrCatalog.TryGetSoundInfoIdByDescription(version, soundSource.WadReferencedSoundName);

                                        var row = new SoundInfoConversionRow(null, soundSource.WadReferencedSoundName);
                                        if (newId == -1)
                                        {
                                            // If sound was not found in catalog, then assign a generic Id and ask to the user
                                            row.NewName = Regex.Replace(soundSource.WadReferencedSoundName, "[^A-Za-z0-9 _]", "").ToUpper();
                                            row.NewId   = lastSoundId++;
                                        }
                                        else
                                        {
                                            // Otherwise, we are lucky, and we can just assign the correct Id
                                            row.NewName = TrCatalog.GetOriginalSoundName(version, (uint)newId);
                                            row.NewId   = newId;
                                        }

                                        conversionList.Add(row);
                                    }
                                }
                                else if (soundSource.EmbeddedSoundInfo != null)
                                {
                                    bool found = false;
                                    foreach (var r in conversionList)
                                    {
                                        if (r.SoundInfo != null && r.SoundInfo == soundSource.EmbeddedSoundInfo)
                                        {
                                            found = true;
                                            break;
                                        }
                                    }

                                    if (found)
                                    {
                                        continue;
                                    }

                                    // Let's first try a search in TrCatalog, maybe we are lucky
                                    // First try to get sound name from TrCatalog

                                    /*int newId = TrCatalog.TryGetSoundInfoIdByDescription(version, soundSource.EmbeddedSoundInfo.Name);
                                     *
                                     * var row = new SoundInfoConversionRow(soundSource.EmbeddedSoundInfo, soundSource.EmbeddedSoundInfo.Name);
                                     * if (newId == -1)
                                     * {
                                     *  // If sound was not found in catalog, then assign a generic Id and ask to the user
                                     *  row.NewName = Regex.Replace(soundSource.EmbeddedSoundInfo.Name, "[^A-Za-z0-9 _]", "").ToUpper();
                                     *  row.NewId = lastSoundId++;
                                     * }
                                     * else
                                     * {
                                     *  // Otherwise, we are lucky, and we can just assign the correct Id
                                     *  row.NewName = TrCatalog.GetOriginalSoundName(version, (uint)newId);
                                     *  row.NewId = newId;
                                     * }*/

                                    // TODO: Lwmte proposed to also there check in TrCatalog, but we should assume that
                                    // embedded sound sources are custom sound sources, created by thhe user with custom samples
                                    // and we should think carrefully about this
                                    var row = new SoundInfoConversionRow(soundSource.EmbeddedSoundInfo, soundSource.EmbeddedSoundInfo.Name);
                                    row.NewName = Regex.Replace(soundSource.EmbeddedSoundInfo.Name, "[^A-Za-z0-9 _]", "").ToUpper();
                                    row.NewId   = lastSoundId++;

                                    // These flags are handle by Tomb Editor and set only for embedded sound sources
                                    row.SaveToXml     = true;
                                    row.ExportSamples = true;

                                    conversionList.Add(row);
                                }
                            }
                        }
                    }
                }

                WadSounds sounds = null;

                // Now we'll show a dialog with all conversion rows and the user will need to make some choices
                if (conversionList.Count != 0)
                {
                    using (var form = new Prj2SoundsConversionDialog(version, conversionList))
                    {
                        if (form.ShowDialog() == DialogResult.Cancel)
                        {
                            return(false);
                        }

                        // If the user has loaded an additional catalog, let's get a pointer to it
                        if (form.Sounds != null)
                        {
                            sounds = form.Sounds;
                        }
                    }
                }

                // Assign new Id and name
                foreach (var row in conversionList)
                {
                    if (row.SoundInfo != null)
                    {
                        row.SoundInfo.Id   = row.NewId;
                        row.SoundInfo.Name = row.NewName;
                    }
                }

                // We'll export only embedded sound sources
                var newSounds = new WadSounds();

                // Remap sound sources
                foreach (var room in level.Rooms)
                {
                    if (room != null)
                    {
                        foreach (var obj in room.Objects)
                        {
                            if (obj is SoundSourceInstance)
                            {
                                SoundSourceInstance soundSource = obj as SoundSourceInstance;
                                if (soundSource.WadReferencedSoundName != null && soundSource.WadReferencedSoundName != "")
                                {
                                    soundSource.SoundId = -1;
                                    foreach (var row in conversionList)
                                    {
                                        if (row.OldName == soundSource.WadReferencedSoundName && row.NewId != -1)
                                        {
                                            soundSource.SoundId = row.NewId;
                                            break;
                                        }
                                    }

                                    soundSource.WadReferencedSoundName = "";
                                    soundSource.EmbeddedSoundInfo      = null;
                                }
                                else if (soundSource.EmbeddedSoundInfo != null)
                                {
                                    // We export embedded sound infos
                                    if (!newSounds.SoundInfos.Contains(soundSource.EmbeddedSoundInfo))
                                    {
                                        newSounds.SoundInfos.Add(soundSource.EmbeddedSoundInfo);
                                    }

                                    soundSource.SoundId = -1;
                                    foreach (var row in conversionList)
                                    {
                                        if (row.SoundInfo == soundSource.EmbeddedSoundInfo && row.NewId != -1)
                                        {
                                            soundSource.SoundId = row.NewId;

                                            // Try to bind samples from additional catalog, if loaded

                                            /*if (sounds != null)
                                             * {
                                             *  WadSoundInfo catalogInfo = sounds.TryGetSoundInfo(row.NewId);
                                             *  if (catalogInfo != null && catalogInfo.Samples.Count > 0)
                                             *  {
                                             *      soundSource.EmbeddedSoundInfo.Samples.Clear();
                                             *      soundSource.EmbeddedSoundInfo.Samples.AddRange(catalogInfo.Samples);
                                             *      // TODO: in theory if valid samples are found in catalog, we shouldn't need to
                                             *      // export them
                                             *      row.ExportSamples = false;
                                             *  }
                                             * }*/

                                            break;
                                        }
                                    }

                                    soundSource.WadReferencedSoundName = "";
                                    soundSource.EmbeddedSoundInfo      = null;
                                }
                            }
                        }
                    }
                }

                // Export samples
                foreach (var row in conversionList)
                {
                    if (row.SoundInfo != null && row.ExportSamples)
                    {
                        var samples = new List <string>();
                        foreach (var sample in row.SoundInfo.Samples)
                        {
                            if (sample.IsLoaded)
                            {
                                string sampleName = Path.GetFileNameWithoutExtension(dest) + "_" + row.NewName.ToLower() + "_" + row.SoundInfo.Samples.IndexOf(sample) + ".wav";
                                samples.Add(sampleName);
                                File.WriteAllBytes(Path.GetDirectoryName(dest) + "\\" + sampleName, sample.Data);
                            }
                        }

                        row.SoundInfo.Samples.Clear();
                        foreach (var sample in samples)
                        {
                            row.SoundInfo.Samples.Add(new WadSample(sample));
                        }
                    }
                }

                // Sort sound infos
                newSounds.SoundInfos.Sort((a, b) => a.Id.CompareTo(b.Id));

                // Make a backup copy
                if (save && src == dest)
                {
                    int    index          = 0;
                    string backupFilename = "";
                    while (true)
                    {
                        backupFilename = dest + "." + index + ".bak";
                        if (!File.Exists(backupFilename))
                        {
                            break;
                        }
                        index++;
                    }

                    File.Copy(src, backupFilename, true);
                }

                // Save Xml to file
                if (newSounds.SoundInfos.Count != 0)
                {
                    string xmlFileName = Path.GetDirectoryName(dest) + "\\" + Path.GetFileNameWithoutExtension(dest) + ".xml";
                    WadSounds.SaveToXml(xmlFileName, newSounds);

                    // Assign Xml to level settings
                    level.Settings.SoundsCatalogs.Add(new ReferencedSoundsCatalog(level.Settings,
                                                                                  level.Settings.MakeRelative(xmlFileName, VariableType.LevelDirectory)));
                }

                level.Settings.SoundSystem = SoundSystem.Xml;

                // Try to get Xml and SFX files
                foreach (var wadRef in level.Settings.Wads)
                {
                    if (wadRef != null && wadRef.LoadException == null)
                    {
                        string wadPath   = level.Settings.MakeAbsolute(wadRef.Path);
                        string extension = Path.GetExtension(wadPath).ToLower();

                        if (extension == ".wad")
                        {
                            string sfxPath = Path.GetDirectoryName(wadPath) + "\\" + Path.GetFileNameWithoutExtension(wadPath) + ".sfx";
                            if (File.Exists(sfxPath))
                            {
                                sounds = WadSounds.ReadFromFile(sfxPath);
                                if (sounds != null)
                                {
                                    level.Settings.SoundsCatalogs.Add(new ReferencedSoundsCatalog(level.Settings,
                                                                                                  level.Settings.MakeRelative(sfxPath, VariableType.LevelDirectory)));
                                }
                            }
                        }
                        else if (extension == ".wad2")
                        {
                            string xmlPath = Path.GetDirectoryName(wadPath) + "\\" + Path.GetFileNameWithoutExtension(wadPath) + ".xml";
                            if (File.Exists(xmlPath))
                            {
                                sounds = WadSounds.ReadFromFile(xmlPath);
                                if (sounds != null)
                                {
                                    level.Settings.SoundsCatalogs.Add(new ReferencedSoundsCatalog(level.Settings,
                                                                                                  level.Settings.MakeRelative(xmlPath, VariableType.LevelDirectory)));
                                }
                            }
                        }
                    }
                }

                // Assign sounds if possible
                foreach (var soundRef in level.Settings.SoundsCatalogs)
                {
                    if (soundRef.LoadException == null)
                    {
                        foreach (var sound in soundRef.Sounds.SoundInfos)
                        {
                            if (!level.Settings.SelectedSounds.Contains(sound.Id))
                            {
                                level.Settings.SelectedSounds.Add(sound.Id);
                            }
                        }
                    }
                }

                // Save Prj2 with Xml sounds
                if (save)
                {
                    using (var stream = File.OpenWrite(dest))
                        Prj2Writer.SaveToPrj2(stream, level);
                }

                return(true);
            }
            catch (Exception ex)
            {
                return(false);
            }
        }