Esempio n. 1
0
 /// <summary>
 /// Update the feature flags.
 /// </summary>
 /// <param name="features">The new feature flags.</param>
 /// <param name="forceFeatureUpdate">If <c>true</c>, apply ROM features even if already set via config file.</param>
 /// <remarks>This also updates the CRC of the header.</remarks>
 public void UpdateFeatures(LuigiFeatureFlags features, bool forceFeatureUpdate)
 {
     if (WouldModifyFeatures(features, forceFeatureUpdate))
     {
         Features = features;
         var flatData = SerializeToBuffer();
         Crc = Crc8.OfBlock(flatData);
     }
 }
Esempio n. 2
0
        /// <summary>
        /// Determines whether the given features would cause a change to this header's feature bits.
        /// </summary>
        /// <param name="features">The proposed new features to apply to the header.</param>
        /// <param name="forceFeatureUpdate">If set to <c>true</c> force feature update, even if the features were set explicitly by a .cfg file.</param>
        /// <returns><c>true</c>, if the new features differ from existing ones, and would cause an update, <c>false</c> otherwise.</returns>
        public bool WouldModifyFeatures(LuigiFeatureFlags features, bool forceFeatureUpdate)
        {
            var willModifyFeatures  = false;
            var hasFlagsFromCfgFile = Features.HasFlag(LuigiFeatureFlags.FeatureFlagsExplicitlySet);

            if (forceFeatureUpdate || !hasFlagsFromCfgFile)
            {
                var currentFlags = Features & ~(LuigiFeatureFlags.UnusedMask | LuigiFeatureFlags.FeatureFlagsExplicitlySet);
                var newFlags     = features & ~(LuigiFeatureFlags.UnusedMask | LuigiFeatureFlags.FeatureFlagsExplicitlySet);
                willModifyFeatures = currentFlags != newFlags;
            }
            return(willModifyFeatures);
        }
        private static ProgramFeatures CreateProgramFeaturesWithoutCoreCompatibility(LuigiFeatureFlags featuresUnderTest)
        {
            var programFeaturesHavingNoLuigiFeatureFlags = new ProgramFeatures()
            {
                Ecs               = EcsFeatures.Incompatible,
                IntellivisionII   = FeatureCompatibility.Incompatible,
                Intellivoice      = FeatureCompatibility.Incompatible,
                KeyboardComponent = KeyboardComponentFeatures.Incompatible,
            };

            if (featuresUnderTest.ExtendedPeripheralCompatabilityBitsVersion() > 0)
            {
                programFeaturesHavingNoLuigiFeatureFlags.Tutorvision = FeatureCompatibility.Incompatible;
            }
            programFeaturesHavingNoLuigiFeatureFlags.SetUnrecongizedRomFeatures();

            return(programFeaturesHavingNoLuigiFeatureFlags);
        }
Esempio n. 4
0
 public void FeatureCompatibility_TutorvisionFeaturesCompatibilityToLuigiFeatureFlags_ProducesCorrectLuigiFeatureFlags(FeatureCompatibility compatibility, LuigiFeatureFlags expectedFeatureFlags)
 {
     Assert.Equal(expectedFeatureFlags, compatibility.ToLuigiFeatureFlags(FeatureCategory.Tutorvision));
 }
Esempio n. 5
0
 public void FeatureCompatibility_KeyboardComponentFeaturesCompatibilityToLuigiFeatureFlags_ProducesCorrectLuigiFeatureFlags(FeatureCompatibility compatibility, LuigiFeatureFlags expectedFeatureFlags)
 {
     Assert.Equal(expectedFeatureFlags, compatibility.ToLuigiFeatureFlags(FeatureCategory.KeyboardComponent));
 }
        public void LuigiFeatureFlags_JlpFlashSectorsToFlags_ProducesCorrectFlags(ushort sectorCount, LuigiFeatureFlags expectedFeatureFlags)
        {
            var featureFlags = sectorCount.MinimumFlashSaveDataSectorsCountToLuigiFeatureFlags();

            Assert.Equal(expectedFeatureFlags, featureFlags);
        }
 public void LuigiFeatureFlags_ToProgramFeatures_ProducesExpectedProgramFeatures(LuigiFeatureFlags featureFlags, ProgramFeatures expectedProgramFeatures)
 {
     Assert.Equal(expectedProgramFeatures, featureFlags.ToProgramFeatures());
 }
        public void LuigiFeatureFlags_LuigiFeatureFlagsForJlpToProgramFeatures_ProduceCorrectlyFormedProgramFeaturesJlpFields(LuigiFeatureFlags flagsToTest, JlpHardwareVersion expectedJlpHardwareVersion, JlpFeatures expectedJlpFeatures)
        {
            var expectedProgramFeatures = CreateProgramFeaturesWithoutCoreCompatibility(flagsToTest);

            expectedProgramFeatures.JlpHardwareVersion = expectedJlpHardwareVersion;
            expectedProgramFeatures.Jlp = expectedJlpFeatures;

            var programFeatures = flagsToTest.ToProgramFeatures();

            Assert.Equal(expectedProgramFeatures, programFeatures);
        }
Esempio n. 9
0
        public void LuigiFileHeader_UpdateFeaturesOnLuigiWithMetadata_UpdatesFeatures(LuigiFeatureFlags newFeatures, bool forceFeatureUpdate)
        {
            var romPath = LuigiFileHeaderTestStorageAccess.Initialize(TestRomResources.TestLuigiScrambledForDevice1Path).First();

            var header           = LuigiFileHeader.GetHeader(romPath);
            var originalCrc      = header.Crc;
            var expectedFeatures = header.WouldModifyFeatures(newFeatures, forceFeatureUpdate) ? newFeatures : header.Features;

            Assert.Equal(0x8B, originalCrc);

            var crcShouldChange = header.Features != expectedFeatures;

            header.UpdateFeatures(newFeatures, forceFeatureUpdate);

            Assert.Equal(expectedFeatures, header.Features);
            Assert.Equal(crcShouldChange, header.Crc != originalCrc);
        }
Esempio n. 10
0
        public void LuigiFileHeader_UpdateFeaturesOnScrambledLuigiRom_UpdatesFeatures(LuigiFeatureFlags newFeatures, bool forceFeatureUpdate)
        {
            var romPath = LuigiFileHeaderTestStorageAccess.Initialize(TestRomResources.TestLuigiScrambledForDevice0Path).First();

            var header      = LuigiFileHeader.GetHeader(romPath);
            var originalCrc = header.Crc;

            Assert.Equal(0xEC, header.Crc);

            var crcShouldChange = header.Features != newFeatures;

            header.UpdateFeatures(newFeatures, forceFeatureUpdate);

            Assert.Equal(newFeatures, header.Features);
            Assert.Equal(crcShouldChange, header.Crc != originalCrc);
        }
Esempio n. 11
0
        public void LuigiFileHeader_WouldModifyFeatures_ProducesCorrectResult(LuigiFeatureFlags newFeatures, bool forceFeatureUpdate, bool expectedWouldModify)
        {
            var header = new LuigiFileHeader();

            Assert.Equal(expectedWouldModify, header.WouldModifyFeatures(newFeatures, forceFeatureUpdate));
        }
Esempio n. 12
0
        /// <summary>
        /// Extracts the version number of extended peripheral compatibility flags data from the feature flags.
        /// </summary>
        /// <param name="featureFlags">The flags whose extended peripheral compatibility flags are needed.</param>
        /// <returns>The extended peripheral flags version number.</returns>
        public static byte ExtendedPeripheralCompatabilityBitsVersion(this LuigiFeatureFlags featureFlags)
        {
            byte compatibilitySubVersion = (byte)((ulong)(featureFlags & LuigiFeatureFlags.ExtendedPeripheralCompatibilityVersionMask) >> ExtendedPeripheralCompatibiltyVersionOffset);

            return(compatibilitySubVersion);
        }
Esempio n. 13
0
        /// <summary>
        /// Extracts the minimum number of JLP Flash save data sectors from the feature flags.
        /// </summary>
        /// <param name="featureFlags">The flags containing the encoded sector count.</param>
        /// <returns>The minimum number of required save data sectors.</returns>
        public static ushort MinimumFlashSaveDataSectors(this LuigiFeatureFlags featureFlags)
        {
            var minimumJlpFlashSaveSectors = (ulong)(featureFlags & LuigiFeatureFlags.JlpFlashMinimumSaveDataSectorCountMask) >> JlpFlashMinimumSaveDataSectorsCountOffset;

            return((ushort)minimumJlpFlashSaveSectors);
        }
Esempio n. 14
0
        /// <summary>
        /// Convert LuigiFeatureFlags into a ProgramFeatures object.
        /// </summary>
        /// <param name="featureFlags">The flags to convert,</param>
        /// <returns>ProgramFeatures representing the compatibility modes described by the feature flags.</returns>
        public static ProgramFeatures ToProgramFeatures(this LuigiFeatureFlags featureFlags)
        {
            var programFeatures = ProgramFeatures.GetUnrecognizedRomFeatures();

            var intellivoiceCompatibililty = (uint)(featureFlags & LuigiFeatureFlags.IntellivoiceMask);

            programFeatures.Intellivoice = (FeatureCompatibility)(intellivoiceCompatibililty >> IntellivoiceOffset);

            var ecsCompatibility = (uint)(featureFlags & LuigiFeatureFlags.EcsMask);

            programFeatures.Ecs = (EcsFeatures)(ecsCompatibility >> EcsOffset);

            var intellivisionIICompatibility = (uint)(featureFlags & LuigiFeatureFlags.IntellivisionIIMask);

            programFeatures.IntellivisionII = (FeatureCompatibility)(intellivisionIICompatibility >> IntellivisionIIOffset);

            var keyboardComponentCompatibility = (uint)(featureFlags & LuigiFeatureFlags.KeyboardComponentMask);

            programFeatures.KeyboardComponent = (KeyboardComponentFeatures)(keyboardComponentCompatibility >> KeyboardComponentOffset);

            var extendedPeripheralCompatibilityVersion = featureFlags.ExtendedPeripheralCompatabilityBitsVersion();

            if (extendedPeripheralCompatibilityVersion > 0)
            {
                var tutorvisionCompatibility = (uint)(featureFlags & LuigiFeatureFlags.TutorVisionMask);
                programFeatures.Tutorvision = (FeatureCompatibility)(tutorvisionCompatibility >> TutorVisionOffset);
            }

            if (extendedPeripheralCompatibilityVersion > 1)
            {
                // TBD
            }

            if (extendedPeripheralCompatibilityVersion > 2)
            {
                // TBD
            }

            var jlpAccelerationCompatibility = (uint)(featureFlags & LuigiFeatureFlags.JlpAccelerationMask);

            programFeatures.Jlp = (JlpFeatures)(jlpAccelerationCompatibility >> JlpAccelerationOffset);

            programFeatures.JlpFlashMinimumSaveSectors = featureFlags.MinimumFlashSaveDataSectors();

            if (programFeatures.JlpFlashMinimumSaveSectors > 0)
            {
                programFeatures.Jlp |= JlpFeatures.SaveDataRequired;
            }

            if ((jlpAccelerationCompatibility != 0) || (programFeatures.JlpFlashMinimumSaveSectors > 0))
            {
                if (programFeatures.JlpHardwareVersion == JlpHardwareVersion.None)
                {
                    programFeatures.JlpHardwareVersion = JlpHardwareVersion.Jlp03;
                }
            }

            var ltoFlashMemoryMapper = (ulong)(featureFlags & LuigiFeatureFlags.LtoFlashMemoryMapperEnabled);

            if (ltoFlashMemoryMapper != 0)
            {
                programFeatures.LtoFlash |= LtoFlashFeatures.LtoFlashMemoryMapped;
            }

            return(programFeatures);
        }
Esempio n. 15
0
        /// <summary>
        /// Prepares a ROM for deployment to a Locutus device.
        /// </summary>
        /// <param name="rom">The ROM being prepared.</param>
        /// <param name="updateMode">Specifies the behavior of the LUIGI file generation.</param>
        /// <returns>The fully qualified path of the prepared output data file to deploy to Locutus.</returns>
        public static string PrepareForDeployment(this IRom rom, LuigiGenerationMode updateMode)
        {
#if REPORT_PERFORMANCE
#if RECORD_PREPARE_FOR_DEPLOYMENT_VISITS
            int visits;
            if (PrepareForDeploymentVisits.TryGetValue(rom.RomPath, out visits))
            {
                PrepareForDeploymentVisits[rom.RomPath] = ++visits;
            }
            else
            {
                PrepareForDeploymentVisits[rom.RomPath] = 1;
            }
#endif // RECORD_PREPARE_FOR_DEPLOYMENT_VISITS
            var stopwatch = System.Diagnostics.Stopwatch.StartNew();
            try
            {
                var stopwatch2 = System.Diagnostics.Stopwatch.StartNew();
#endif // REPORT_PERFORMANCE
            rom.Validate();
#if REPORT_PERFORMANCE
            stopwatch2.Stop();
            _accumulatedPrepareValidateTime += stopwatch2.Elapsed;
#endif // REPORT_PERFORMANCE
            if ((updateMode == LuigiGenerationMode.Passthrough) && (rom.Format == RomFormat.Luigi))
            {
                return(rom.RomPath);
            }
#if REPORT_PERFORMANCE
            stopwatch2.Restart();
            var stopwatch3 = System.Diagnostics.Stopwatch.StartNew();
#endif // REPORT_PERFORMANCE
            var jzIntvConfiguration = SingleInstanceApplication.Instance.GetConfiguration <INTV.JzIntv.Model.Configuration>();
            var converterApps       = jzIntvConfiguration.GetConverterApps(rom, RomFormat.Luigi);
            if (!converterApps.Any())
            {
                converterApps = new[] { new Tuple <string, RomFormat>(JustCopy, RomFormat.Luigi) };
            }
            var converterApp = converterApps.First(); // rom.GetConverterApp(jzIntvConfiguration);
            if ((converterApp.Item1 != JustCopy) && (string.IsNullOrEmpty(converterApp.Item1) || !System.IO.File.Exists(converterApp.Item1)) && (rom.Format != RomFormat.Luigi))
            {
                var message = string.Format(System.Globalization.CultureInfo.CurrentCulture, Resources.Strings.RomToLuigiFailed_ConversionToolNotFound_Error_Format, converterApp);
                throw new LuigiFileGenerationException(message, Resources.Strings.RomToLuigiFailed_ConversionToolNotFound_Error_Description);
            }
#if REPORT_PERFORMANCE
            stopwatch3.Stop();
            _accumulatedPrepareConverterAppsTime += stopwatch3.Elapsed;
            stopwatch3.Restart();
#endif // REPORT_PERFORMANCE
            var romStagingArea   = SingleInstanceApplication.Instance.GetConfiguration <Configuration>().RomsStagingAreaPath;
            var stagingAreaPath  = rom.GetStagingAreaPath(romStagingArea);
            var cachedRomPath    = rom.GetCachedRomFilePath(stagingAreaPath);
            var cachedConfigPath = rom.GetCachedConfigFilePath(stagingAreaPath);
            var luigiFile        = rom.GetOutputFilePath(stagingAreaPath, ProgramFileKind.LuigiFile);
#if REPORT_PERFORMANCE
            stopwatch3.Stop();
            _accumulatedPrepareStagingTime += stopwatch3.Elapsed;
            stopwatch3.Restart();
#endif // REPORT_PERFORMANCE

            bool createLuigiFile = true;
            bool changed;
            bool isSourceFileInCache = rom.IsInCache(stagingAreaPath, out changed);
#if REPORT_PERFORMANCE
            stopwatch3.Stop();
            _accumulatedPrepareCacheLookupTime += stopwatch3.Elapsed;
#endif // REPORT_PERFORMANCE

#if REPORT_PERFORMANCE
            stopwatch2.Stop();
            _accumulatedPrepareSetupTime += stopwatch2.Elapsed;

            stopwatch2.Restart();
#endif // REPORT_PERFORMANCE
            var luigiHeader = rom.GetLuigiHeader();
            if (luigiHeader != null)
            {
                // If the given ROM is already a LUIGI file, see if we can determine whether it's already in our cache.
#if REPORT_OLD_LUIGI_FILES
                System.Diagnostics.Debug.Assert(luigiHeader.Version > 0, "Really, you've got some OLD LUIGI files. Delete them.");
#endif // REPORT_OLD_LUIGI_FILES
                var crc24 = INTV.Core.Utility.Crc24.OfFile(rom.RomPath);
                var size  = new System.IO.FileInfo(rom.RomPath).Length;
                var entry = CacheIndex.Find(crc24, (uint)size);
                isSourceFileInCache = entry != null;
                if (isSourceFileInCache)
                {
                    // Cases have been found in which, by moving files around on disk, the staging area path can change.
                    // The result of this, though, is that the *new* path in the cache is different than the extant one
                    // found in the cache. In this case, if the entry's location is different than the newly computed
                    // one, ignore the cache entry and make a new one by acting as if the file is not in the cache.
                    // FIXME This is a lazy fix. A better fix would be to remove the cached files and existing cache
                    // entry and re-add this new one. Or patch up the existing entry. Hell, maybe scrap the entire cache
                    // altogether as it's a bit of a bug farm and creating LUIGI files isn't all *that* expensive.
                    var stagingDirectory   = System.IO.Path.GetFileName(stagingAreaPath);
                    var stagingPathChanged = !entry.LuigiPath.StartsWith(stagingDirectory);
                    if (stagingPathChanged)
                    {
                        isSourceFileInCache = false;
                    }
                    else
                    {
                        luigiFile     = System.IO.Path.Combine(romStagingArea, entry.LuigiPath);
                        cachedRomPath = System.IO.Path.Combine(romStagingArea, entry.RomPath);
                        if (!string.IsNullOrEmpty(entry.CfgPath))
                        {
                            cachedConfigPath = System.IO.Path.Combine(romStagingArea, entry.CfgPath);
                        }
                    }
                }
            }
#if REPORT_PERFORMANCE
            stopwatch2.Stop();
            _accumulatedPrepareLuigiHeaderTime += stopwatch2.Elapsed;

            stopwatch2.Restart();
#endif // REPORT_PERFORMANCE

            if (isSourceFileInCache)
            {
                createLuigiFile = changed || !System.IO.File.Exists(luigiFile);
            }
            if (!isSourceFileInCache || changed)
            {
                cachedRomPath.ClearReadOnlyAttribute();
                cachedConfigPath.ClearReadOnlyAttribute();
                System.IO.File.Copy(rom.RomPath, cachedRomPath, true);
                if (!string.IsNullOrWhiteSpace(cachedConfigPath) && !string.IsNullOrEmpty(rom.ConfigPath) && System.IO.File.Exists(rom.ConfigPath) && (rom.ConfigPath != rom.RomPath))
                {
                    System.IO.File.Copy(rom.ConfigPath, cachedConfigPath, true);
                }
                else if ((string.IsNullOrEmpty(rom.ConfigPath) || !System.IO.File.Exists(rom.ConfigPath)) && System.IO.File.Exists(cachedConfigPath))
                {
                    // The ROM's configuration file path doesn't exist, but there's one in the cache. Remove it.
                    FileUtilities.DeleteFile(cachedConfigPath, false, 2);
                    cachedConfigPath = null; // this is OK, because the ClearReadOnlyAttribute() extension method is null-safe
                }
                cachedRomPath.ClearReadOnlyAttribute();
                cachedConfigPath.ClearReadOnlyAttribute();
            }
#if REPORT_PERFORMANCE
            stopwatch2.Stop();
            _accumulatedPrepareCachedChangedTime += stopwatch2.Elapsed;

            stopwatch2.Restart();
#endif // REPORT_PERFORMANCE

            if (createLuigiFile || ((updateMode == LuigiGenerationMode.FeatureUpdate) || (updateMode == LuigiGenerationMode.Reset)))
            {
                var argument = "\"" + cachedRomPath + "\"" + " \"" + luigiFile + "\"";
                var result   = -1;
                if (JustCopy == converterApp.Item1)
                {
                    System.IO.File.Copy(rom.RomPath, luigiFile, true);
                    result = 0;
                }
                else
                {
                    result = INTV.Shared.Utility.RunExternalProgram.Call(converterApp.Item1, argument, stagingAreaPath);
                }
                if (result == 0)
                {
                    if (!System.IO.File.Exists(luigiFile))
                    {
                        var message = string.Format(System.Globalization.CultureInfo.CurrentCulture, Resources.Strings.RomToLuigiFailed_OutputFileNotFound_Error_Format, rom.RomPath, System.IO.Path.GetFileNameWithoutExtension(luigiFile));
                        throw new LuigiFileGenerationException(message, Resources.Strings.RomToLuigiFailed_OutputFileNotFound_Error_Description_Format);
                    }
                    else if ((new System.IO.FileInfo(luigiFile)).Length > Device.TotalRAMSize)
                    {
                        var message = string.Format(System.Globalization.CultureInfo.CurrentCulture, Resources.Strings.RomToLuigiFailed_TooLarge_Error_Message_Format, rom.RomPath, luigiFile);
                        throw new LuigiFileGenerationException(message, Resources.Strings.RomToLuigiFailed_TooLarge_Description);
                    }

                    var description = INTV.Shared.Model.Program.ProgramCollection.Roms.FirstOrDefault(d => rom.IsEquivalentTo(d.Rom, RomComparerStrict.Default));
                    if (description != null)
                    {
                        LuigiFeatureFlags features = LuigiFeatureFlags.None;
#if DEBUG
                        var complainAboutOldLuigiFile = false;
#endif // DEBUG
                        luigiHeader = LuigiFileHeader.GetHeader(luigiFile);
                        features    = description.Features.LuigiFeaturesLo;
#if DEBUG
                        var isRecognizedRom     = !description.Features.GeneralFeatures.HasFlag(GeneralFeatures.UnrecognizedRom);
                        var hasFlagsFromCfgFile = luigiHeader.Features.HasFlag(LuigiFeatureFlags.FeatureFlagsExplicitlySet);
                        complainAboutOldLuigiFile = isRecognizedRom && hasFlagsFromCfgFile && ((luigiHeader.Features & ~LuigiFeatureFlags.FeatureFlagsExplicitlySet) != features);
#endif // DEBUG
#if DEBUG
                        if (complainAboutOldLuigiFile)
                        {
                            var message = "Known ROM has explicit flags from utility that are different than those set by LUI:\n\n";
                            message += "  LUI: " + features + "\n";
                            message += "  Utility: " + (luigiHeader.Features & ~LuigiFeatureFlags.FeatureFlagsExplicitlySet);
                            INTV.Shared.View.OSMessageBox.Show(message, "Feature Flags Inconsistency");
                        }
#endif // DEBUG
                        if (luigiHeader.WouldModifyFeatures(features, updateMode == LuigiGenerationMode.FeatureUpdate))
                        {
                            using (var file = System.IO.File.Open(luigiFile, System.IO.FileMode.Open, System.IO.FileAccess.ReadWrite))
                            {
                                luigiHeader.UpdateFeatures(features, updateMode == LuigiGenerationMode.FeatureUpdate);
                                file.Seek(0, System.IO.SeekOrigin.Begin);
                                luigiHeader.Serialize(new Core.Utility.BinaryWriter(file));
                            }
                        }
                    }
                    try
                    {
                        var cacheIndexEntry = new CacheIndexEntry(rom, cachedRomPath);
                        CacheIndex.Instance.AddEntry(cacheIndexEntry);
                    }
                    catch (Exception e)
                    {
                        var message = string.Format(System.Globalization.CultureInfo.CurrentCulture, Resources.Strings.PrepareForDeployment_ErrorCreatingCacheEntryFormat, rom.RomPath);
                        throw new LuigiFileGenerationException(message, e.Message, e);
                    }
                }
                else
                {
                    var message     = string.Format(System.Globalization.CultureInfo.CurrentCulture, Resources.Strings.RomToLuigiFailed_InvalidOperation_Error_Message_Format, result);
                    var description = string.Format(System.Globalization.CultureInfo.CurrentCulture, Resources.Strings.RomToLuigiFailed_Error_Description_Format, converterApp);
                    throw new LuigiFileGenerationException(message, description);
                }
            }
            else
            {
                // If this is a different ROM that produces the same LUIGI, add an entry.
                var crc24 = INTV.Core.Utility.Crc24.OfFile(luigiFile);
                var size  = (uint)(new System.IO.FileInfo(luigiFile)).Length;
                if (CacheIndex.Find(crc24, size) == null)
                {
                    try
                    {
                        var cacheIndexEntry = new CacheIndexEntry(rom, cachedRomPath);
                        CacheIndex.Instance.AddEntry(cacheIndexEntry);
                    }
                    catch (Exception e)
                    {
                        var message = string.Format(System.Globalization.CultureInfo.CurrentCulture, Resources.Strings.PrepareForDeployment_ErrorCreatingCacheEntryFormat, rom.RomPath);
                        throw new LuigiFileGenerationException(message, e.Message, e);
                    }
                }
            }
            ////catch (System.IO.PathTooLongException e)
            ////catch (System.IO.IOException e)
            ////catch (UnauthorizedAccessException e)
            ////catch (InvalidOperationException e)
            ////catch (LuigiFileGenerationException e)
#if REPORT_PERFORMANCE
            stopwatch2.Stop();
            _accumulatedPrepareLuigiUpdateTime += stopwatch2.Elapsed;
#endif // REPORT_PERFORMANCE

            if (string.IsNullOrEmpty(luigiFile) || !System.IO.File.Exists(luigiFile))
            {
                var message     = string.Format(System.Globalization.CultureInfo.CurrentCulture, Resources.Strings.RomToLuigiFailed_Error_Description_Format, rom);
                var description = string.Format(System.Globalization.CultureInfo.CurrentCulture, Resources.Strings.RomToLuigiFailed_InvalidOutputFileFormat, luigiFile);
                throw new LuigiFileGenerationException(message, description);
            }

#if REPORT_PERFORMANCE
            stopwatch.Stop();
#endif // REPORT_PERFORMANCE
            return(luigiFile);

#if REPORT_PERFORMANCE
        }

        finally
        {
            stopwatch.Stop();
            _accumulatedPrepareTime += stopwatch.Elapsed;
        }
#endif // REPORT_PERFORMANCE
        }