Example #1
0
        public void IProgramInformation_GetDatabaseCodeOnUnmergedProgramInformation_ReturnsExpectedCode()
        {
            var information = new UnmergedProgramInformation(
                "dude",
                "The Big Lebowski",
                "Coen Brothers",
                "1998",
                new[] { 1234u },
                new[] { "Duuude!" },
                new[] { 0 },
                ProgramFeatures.GetUnrecognizedRomFeatures());

            Assert.Equal("dude", information.GetDatabaseCode());
        }
 /// <inheritdoc />
 public override void Initialize(ProgramFeatures features)
 {
     base.Initialize(features);
     _jlpVersion = JlpVersions.FirstOrDefault(e => (e != null) && e.Flags == (uint)features.JlpHardwareVersion);
     _enableAcceleratorsAtStartup = features.Jlp.HasFlag(JlpFeatures.Tolerates);
     _usesFlashStorage            = features.Jlp.HasFlag(JlpFeatures.SaveDataOptional) || features.Jlp.HasFlag(JlpFeatures.SaveDataRequired);
     _minimumFlashSectors         = features.JlpFlashMinimumSaveSectors;
     _usesSerialPort = features.Jlp.HasFlag(JlpFeatures.SerialPortEnhanced) || features.Jlp.HasFlag(JlpFeatures.SerialPortRequired);
     _serialPort     = SerialPortOptions.FirstOrDefault(s => UsesSerialPort && (s != null) && features.Jlp.HasFlag((JlpFeatures)s.Flags));
     _usesLEDs       = features.Jlp.HasFlag(JlpFeatures.UsesLEDs);
     RaiseAllPropertiesChanged();
     UpdateUsesFlashStorage(_usesFlashStorage);
     UpdateSerialPortUsage(_usesSerialPort);
     UpdateFlashUsageLevel(_minimumFlashSectors);
 }
        /// <inheritdoc />
        public void OnImportsSatisfied()
        {
            var defaultFeatures = new ProgramFeatures();
            var featureGroups   = new List <Tuple <string, double, IRomFeaturesConfigurationPage> >();

            foreach (var featureGroup in FeatureGroupImplementations)
            {
                var featurePage = featureGroup.Value;
                featurePage.Initialize(defaultFeatures);
                featureGroups.Add(new Tuple <string, double, IRomFeaturesConfigurationPage>(featureGroup.Metadata.Name, featureGroup.Metadata.Weight, featurePage));
                PreparePage(featurePage);
            }
            FeatureGroups    = new ObservableCollection <IRomFeaturesConfigurationPage>(featureGroups.OrderBy(g => g.Item2).Select(g => g.Item3));
            CurrentSelection = FeatureGroups.First();
        }
        public void MergedProgramInformationTable_MergedWithNonEmptyTable_HasPrograms()
        {
            var mergedInformationTable = new MergedProgramInformationTable();

            var testProgramInformation = new TestProgramInformation()
            {
                Title = "Marty McTesterson", Features = ProgramFeatures.GetUnrecognizedRomFeatures()
            };

            testProgramInformation.AddCrcs(1);
            var table = new TestProgramInformationTable();

            table.AddEntries(testProgramInformation);
            mergedInformationTable.MergeTable(table);

            Assert.True(mergedInformationTable.Programs.Any());
        }
        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);
        }
        public void MergedProgramInformationTable_FindRomWithProgramIdentifier_FindsInformationAsExpected()
        {
            var mergedInformationTable = new MergedProgramInformationTable();
            var testProgramIdentifier  = new ProgramIdentifier(0x123u, 0x456u);
            var testProgramInformation = new TestProgramInformation()
            {
                Title = "Buffy Buckingham", Features = ProgramFeatures.GetUnrecognizedRomFeatures()
            };

            testProgramInformation.AddCrcs(3);
            testProgramInformation.AddCrc(testProgramIdentifier.DataCrc, "Version 0", IncompatibilityFlags.Tutorvision, testProgramIdentifier.OtherData);
            var table = new TestProgramInformationTable();

            table.AddEntries(testProgramInformation);
            mergedInformationTable.MergeTable(table);

            var foundInformation = mergedInformationTable.FindProgram(testProgramIdentifier);

            Assert.NotNull(foundInformation);
        }
        /// <summary>
        /// Initialize the view model and all of the known feature page editors.
        /// </summary>
        /// <param name="description">The description of the program whose features are being edited.</param>
        /// <param name="inplaceEditor">The in-place editor hosting this editor. Used for lifetime control.</param>
        public void Initialize(ProgramDescription description, IInPlaceEditor inplaceEditor)
        {
            InPlaceEditor       = inplaceEditor;
            Description         = description;
            ShowRevertToDefault = false;
            switch (description.ProgramInformation.DataOrigin)
            {
            case ProgramInformationOrigin.UserDefined:
            case ProgramInformationOrigin.None:
                break;

            default:
                ShowRevertToDefault = true;
                break;
            }
            OriginalFeatures             = description.Features.Clone();
            EditFeatures                 = OriginalFeatures.Clone();
            EditsPriorToRevertToDatabase = null;
            InitializeToEditFeatures();
        }
Example #8
0
        /// <summary>
        /// Produces an enumerable containing icons that represent program features.
        /// </summary>
        /// <param name="features">The features to represent as icons.</param>
        /// <returns>The enumerable containing visuals representing the program features.</returns>
        public static IEnumerable <ProgramFeatureImageViewModel> ToFeatureViewModels(this ProgramFeatures features)
        {
            var anyIncompatibilities = false;
            var featuresToAdd        = features.GeneralFeatures.GetImagesForFlags(GeneralFeatureSet.Data, CompatibilityCheckMode.None, ref anyIncompatibilities);

            var images = new List <ProgramFeatureImageViewModel>(featuresToAdd);

            featuresToAdd = features.KeyboardComponent.GetImagesForFlags(KeyboardComponentFeatureSet.Data, CompatibilityCheckMode.Default, ref anyIncompatibilities);
            var requiresPeripheral = featuresToAdd.ContainsRequiredFeature();

            images.AddRange(featuresToAdd);
            featuresToAdd = features.SuperVideoArcade.GetImagesForFlags(SuperVideoArcadeFeatureSet.Data, CompatibilityCheckMode.Default, ref anyIncompatibilities);
            images.AddRange(featuresToAdd);
            featuresToAdd       = features.Intellivoice.GetImagesForFlags(IntellivoiceFeatureSet.Data, CompatibilityCheckMode.Default, ref anyIncompatibilities);
            requiresPeripheral |= featuresToAdd.ContainsRequiredFeature();
            images.AddRange(featuresToAdd);
            featuresToAdd = features.IntellivisionII.GetImagesForFlags(IntellivisionIIFeatureSet.Data, CompatibilityCheckMode.Default, ref anyIncompatibilities);
            images.AddRange(featuresToAdd);
            featuresToAdd       = features.Ecs.GetImagesForFlags(EcsFeatureSet.Data, CompatibilityCheckMode.Default, ref anyIncompatibilities);
            requiresPeripheral |= featuresToAdd.ContainsRequiredFeature();
            images.AddRange(featuresToAdd);
            featuresToAdd       = features.Tutorvision.GetImagesForFlags(TutorvisionFeatureSet.Data, CompatibilityCheckMode.Default, ref anyIncompatibilities);
            requiresPeripheral |= featuresToAdd.ContainsRequiredFeature();
            images.AddRange(featuresToAdd);
            featuresToAdd       = features.Intellicart.GetImagesForFlags(IntellicartFeatureSet.Data, CompatibilityCheckMode.Default, ref anyIncompatibilities);
            requiresPeripheral |= featuresToAdd.ContainsRequiredFeature();
            images.AddRange(featuresToAdd);
            featuresToAdd = features.CuttleCart3.GetImagesForFlags(CuttleCart3FeatureSet.Data, CompatibilityCheckMode.Default, ref anyIncompatibilities);
            images.AddRange(featuresToAdd);
            featuresToAdd       = features.Jlp.GetImagesForFlags(JlpFeatureSet.Data, CompatibilityCheckMode.Default, ref anyIncompatibilities);
            requiresPeripheral |= featuresToAdd.ContainsRequiredFeature();
            images.AddRange(featuresToAdd);
            featuresToAdd       = features.LtoFlash.GetImagesForFlags(LtoFlashFeatureSet.Data, CompatibilityCheckMode.Default, ref anyIncompatibilities);
            requiresPeripheral |= featuresToAdd.ContainsRequiredFeature();
            images.AddRange(featuresToAdd);
            featuresToAdd       = features.Bee3.GetImagesForFlags(Bee3FeatureSet.Data, CompatibilityCheckMode.Default, ref anyIncompatibilities);
            requiresPeripheral |= featuresToAdd.ContainsRequiredFeature();
            images.AddRange(featuresToAdd);
            featuresToAdd       = features.Hive.GetImagesForFlags(HiveFeatureSet.Data, CompatibilityCheckMode.Default, ref anyIncompatibilities);
            requiresPeripheral |= featuresToAdd.ContainsRequiredFeature();
            images.AddRange(featuresToAdd);

            var ntscMode = features.Ntsc.GetImagesForFlags(NtscFeatureSet.Data, CompatibilityCheckMode.OnlyCheckIncompatible, ref anyIncompatibilities).FirstOrDefault();
            var palMode  = features.Pal.GetImagesForFlags(PalFeatureSet.Data, CompatibilityCheckMode.OnlyCheckIncompatible, ref anyIncompatibilities).FirstOrDefault();

            if (palMode != null)
            {
                if (images.Any())
                {
                    images.Insert(0, palMode);
                }
                else
                {
                    images.Add(palMode);
                }
            }
            if (ntscMode != null)
            {
                if (images.Any())
                {
                    images.Insert(0, ntscMode);
                }
                else
                {
                    images.Add(ntscMode);
                }
            }

            if (!requiresPeripheral && (!anyIncompatibilities || !images.Any()) && !features.GeneralFeatures.HasFlag(GeneralFeatures.UnrecognizedRom))
            {
                if (!images.Any())
                {
                    images.Add(UniversallyCompatible);
                }
            }

            return(images);
        }
Example #9
0
        /// <inheritdoc/>
        protected override uint DeserializePayload(INTV.Core.Utility.BinaryReader reader)
        {
            var remainingPayload = Length;

            if (remainingPayload < 3)
            {
                System.Diagnostics.Debug.WriteLine("Too few bytes in feature metadata!");
            }
            if (remainingPayload > 0)
            {
                // The first byte contains compatibility:
                // .   7   6   5   4   3   2   1   0
                // +---+---+---+---+---+---+---+---+
                // |  ECS  | rsvd | VOICE | KEYBD |    byte 0
                // +---+---+---+---+---+---+---+---+
                Features = ProgramFeatures.DefaultFeatures.Clone();
                var featureBits = reader.ReadByte();
                --remainingPayload;

                // Bits 0,1 are Keyboard Component compatibility.
                var compatibility = RawFeatureToFeatureCompatibility(featureBits & FeatureMask);
                Features.KeyboardComponent = (KeyboardComponentFeatures)compatibility;

                // Bits 2,3 are Intellivoice compatibility.
                compatibility         = RawFeatureToFeatureCompatibility((featureBits >> 2) & FeatureMask);
                Features.Intellivoice = compatibility;

                // Bits 4,5 are reserved (used to be 4-controller capability) (ignored)
                ////compatibility = RawFeatureToFeatureCompatibility((featureBits >> 4) & FeatureMask);

                // Bits 6,7 are ECS compatibility.
                compatibility = RawFeatureToFeatureCompatibility((featureBits >> 6) & FeatureMask);
                Features.Ecs  = (EcsFeatures)compatibility;
            }
            if (remainingPayload > 0)
            {
                // The second byte contains more compatibility:
                // .   7   6   5   4   3   2   1   0
                // +---+---+---+---+---+---+---+---+
                // | rsvd  | rsvd  | TUTOR | INTY2 |    byte 1
                // +---+---+---+---+---+---+---+---+
                var featureBits = reader.ReadByte();
                --remainingPayload;

                // Bits 0,1 are Intellivision II compatibility.
                var compatibility = RawFeatureToFeatureCompatibility(featureBits & FeatureMask);
                Features.IntellivisionII = compatibility;

                // Bits 2,3 are TutorVision compatibility.
                compatibility        = RawFeatureToFeatureCompatibility((featureBits >> 2) & FeatureMask);
                Features.Tutorvision = compatibility;
            }
            if (remainingPayload > 0)
            {
                // The third byte contains emulator-specific guidance.
                // .    7    6    5    4    3    2    1    0
                // +----+----+----+----+----+----+----+----+
                // |rsvd|rsvd|rsvd|rsvd|rsvd|rsvd|rsvd|rsvd|    byte 2
                // +----+----+----+----+----+----+----+----+

                // We're going to ignore this byte.
                reader.ReadByte();
                --remainingPayload;
            }
            if (remainingPayload > 1)
            {
                // These two bytes contain JLP compatibility.
                // .    7    6    5    4    3    2    1    0
                // +----+----+----+----+----+----+----+----+
                // |JLP Accel|LTOM|   Reserved   |JLPf 9..8|    byte 3
                // +----+----+----+----+----+----+----+----+
                var featureBits = reader.ReadByte();
                --remainingPayload;
                var compatibility = (FeatureCompatibility)((featureBits >> 6) & FeatureMask);
                Features.Jlp = (JlpFeatures)compatibility;
                if (((1 << 5) & featureBits) != 0)
                {
                    Features.LtoFlash |= LtoFlashFeatures.LtoFlashMemoryMapped;
                }
                var flashSectors = (ushort)((featureBits & FeatureMask) << 8);

                // .    7    6    5    4    3    2    1    0
                // +----+----+----+----+----+----+----+----+
                // |          JLP Flash bits 7..0          |    byte 4
                // +----+----+----+----+----+----+----+----+
                flashSectors |= reader.ReadByte();
                --remainingPayload;
                Features.JlpFlashMinimumSaveSectors = flashSectors;
                if (Features.Jlp != JlpFeatures.Incompatible)
                {
                    Features.JlpHardwareVersion = JlpHardwareVersion.Jlp03; // Assume minimal hardware version needed
                }
            }
            if (remainingPayload > 0)
            {
                reader.BaseStream.Seek(remainingPayload, System.IO.SeekOrigin.Current);
            }
            return(Length);
        }
Example #10
0
        /// <summary>
        /// Creates a condensed set of incompatibility features from a full set of ProgramFeatures.
        /// </summary>
        /// <param name="programFeatures">The program features from which to create a condensed set of incompatibility flags.</param>
        /// <returns>The incompatibility flags.</returns>
        public static IncompatibilityFlags ToIncompatibilityFlags(this ProgramFeatures programFeatures)
        {
            var incompatibilityFlags = IncompatibilityFlags.None;

            if (programFeatures.Ntsc == FeatureCompatibility.Incompatible)
            {
                incompatibilityFlags |= IncompatibilityFlags.Ntsc;
            }
            if (programFeatures.Pal == FeatureCompatibility.Incompatible)
            {
                incompatibilityFlags |= IncompatibilityFlags.Pal;
            }
            if (programFeatures.KeyboardComponent == KeyboardComponentFeatures.Incompatible)
            {
                incompatibilityFlags |= IncompatibilityFlags.KeyboardComponent;
            }
            if (programFeatures.SuperVideoArcade == FeatureCompatibility.Incompatible)
            {
                incompatibilityFlags |= IncompatibilityFlags.SuperVideoArcade;
            }
            if (programFeatures.SuperVideoArcade == FeatureCompatibility.Enhances)
            {
                incompatibilityFlags |= IncompatibilityFlags.SuperVideoArcadeAltered;
            }
            if (programFeatures.Intellivoice == FeatureCompatibility.Incompatible)
            {
                incompatibilityFlags |= IncompatibilityFlags.Intellivoice;
            }
            if (programFeatures.IntellivisionII == FeatureCompatibility.Incompatible)
            {
                incompatibilityFlags |= IncompatibilityFlags.IntellivisionII;
            }
            if (programFeatures.IntellivisionII == FeatureCompatibility.Enhances)
            {
                incompatibilityFlags |= IncompatibilityFlags.IntellivisionIIAltered;
            }
            if (programFeatures.Ecs == EcsFeatures.Incompatible)
            {
                incompatibilityFlags |= IncompatibilityFlags.Ecs;
            }
            if (programFeatures.Tutorvision == FeatureCompatibility.Incompatible)
            {
                incompatibilityFlags |= IncompatibilityFlags.Tutorvision;
            }
            if (programFeatures.Intellicart == IntellicartCC3Features.Incompatible)
            {
                incompatibilityFlags |= IncompatibilityFlags.Intellicart;
            }
            if (programFeatures.CuttleCart3 == CuttleCart3Features.Incompatible)
            {
                incompatibilityFlags |= IncompatibilityFlags.CuttleCart3;
            }
            if (programFeatures.Jlp == JlpFeatures.Incompatible)
            {
                incompatibilityFlags |= IncompatibilityFlags.Jlp;
            }
            if (programFeatures.LtoFlash == LtoFlashFeatures.Incompatible)
            {
                incompatibilityFlags |= IncompatibilityFlags.LtoFlash;
            }
            if (programFeatures.Bee3 == Bee3Features.Incompatible)
            {
                incompatibilityFlags |= IncompatibilityFlags.Bee3;
            }
            if (programFeatures.Hive == HiveFeatures.Incompatible)
            {
                incompatibilityFlags |= IncompatibilityFlags.Hive;
            }
            return(incompatibilityFlags);
        }
 /// <inheritdoc />
 public virtual void Initialize(ProgramFeatures features)
 {
     Features = features;
 }
 /// <summary>
 /// Reverts any changes made to the features, resetting to values originally supplied to the editor.
 /// </summary>
 public void RevertChanges()
 {
     EditFeatures = OriginalFeatures.Clone();
     EditsPriorToRevertToDatabase = null;
     InitializeToEditFeatures();
 }
 /// <summary>
 /// Reverts any changes made to the features, resetting to values from the built-in program database.
 /// </summary>
 public void RevertToDatabase()
 {
     EditsPriorToRevertToDatabase = EditFeatures.Clone();
     EditFeatures = Description.ProgramInformation.Features.Clone();
     InitializeToEditFeatures();
 }
 public void LuigiFeatureFlags_ToProgramFeatures_ProducesExpectedProgramFeatures(LuigiFeatureFlags featureFlags, ProgramFeatures expectedProgramFeatures)
 {
     Assert.Equal(expectedProgramFeatures, featureFlags.ToProgramFeatures());
 }
 public ProgramFeaturesBuilder()
 {
     _programFeatures = ProgramFeatures.DefaultFeatures.Clone();
 }
 public void LuigiFeatureFlags2_ToProgramFeatures_ProducesCorrectFeatures(LuigiFeatureFlags2 featureBits)
 {
     Assert.Equal(ProgramFeatures.GetUnrecognizedRomFeatures(), featureBits.ToProgramFeatures());
 }
        public void ProgramFeatures_ToIncompatibilityFlagsWithnULLFeatures_ThrowsNullReferenceException()
        {
            ProgramFeatures features = null;

            Assert.Throws <NullReferenceException>(() => features.ToIncompatibilityFlags());
        }
Example #18
0
 /// <summary>
 /// Clear the features that are used when an 'unrecognized' ROM is being handled.
 /// </summary>
 /// <param name="programFeatures">The <see cref="ProgramFeatures"/> whose unrecognized-ness is to be cleared.</param>
 public static void ClearUnrecongizedRomFeatures(this ProgramFeatures programFeatures)
 {
     programFeatures.GeneralFeatures &= ~GeneralFeatures.UnrecognizedRom;
     programFeatures.Ntsc             = ProgramFeatures.DefaultFeatures.Ntsc;
     programFeatures.Pal              = ProgramFeatures.DefaultFeatures.Pal;
 }
Example #19
0
        public void IProgramInformation_MergeAllFieldsFromMultipleSources_CorrectlyMerges()
        {
            var emptyInformation = new TestProgramInformation();
            var titleSource      = new Tuple <IProgramInformation, ProgramInformationMergeFieldsFlags>(new TestProgramInformation()
            {
                Title = "Hey der"
            }, ProgramInformationMergeFieldsFlags.All);
            var vendorSource = new Tuple <IProgramInformation, ProgramInformationMergeFieldsFlags>(new TestProgramInformation()
            {
                Title = " Buddy, ", Vendor = "howya doin"
            }, ProgramInformationMergeFieldsFlags.All);
            var yearSource = new Tuple <IProgramInformation, ProgramInformationMergeFieldsFlags>(new TestProgramInformation()
            {
                Vendor = "ya hoser", Year = "1984"
            }, ProgramInformationMergeFieldsFlags.All);
            var features       = (ProgramFeatures) new ProgramFeaturesBuilder().WithInitialFeatures(ProgramFeatures.GetUnrecognizedRomFeatures()).WithSuperVideoArcadeCompatibility(FeatureCompatibility.Enhances).Build();
            var featuresSource = new Tuple <IProgramInformation, ProgramInformationMergeFieldsFlags>(new TestProgramInformation()
            {
                Features = features, Year = "1988"
            }, ProgramInformationMergeFieldsFlags.All);
            var shortNameSource = new Tuple <IProgramInformation, ProgramInformationMergeFieldsFlags>(new TestProgramInformation()
            {
                ShortName = "ShortRound"
            }, ProgramInformationMergeFieldsFlags.All);
            var crcsSource = new Tuple <IProgramInformation, ProgramInformationMergeFieldsFlags>(new TestProgramInformation(), ProgramInformationMergeFieldsFlags.All);

            Assert.True(crcsSource.Item1.AddCrc(0x246801u, "uffdah", IncompatibilityFlags.KeyboardComponent));

            var mergedInformation = emptyInformation.Merge(ProgramInformationMergeFieldsFlags.All, titleSource, vendorSource, yearSource, featuresSource, shortNameSource, crcsSource);

            Assert.Equal(titleSource.Item1.Title, mergedInformation.Title);
            Assert.Equal(vendorSource.Item1.Vendor, mergedInformation.Vendor);
            Assert.Equal(yearSource.Item1.Year, mergedInformation.Year);
            Assert.Equal(featuresSource.Item1.Features, mergedInformation.Features);
            Assert.Equal(shortNameSource.Item1.ShortName, mergedInformation.ShortName);
            Assert.Equal(crcsSource.Item1.Crcs, mergedInformation.Crcs);
        }
Example #20
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);
        }