Example #1
0
 /// <summary>
 /// Creates a new instance if the UnmergedProgram structure.
 /// </summary>
 /// <param name="code">INTV Funhouse code for the ROM.</param>
 /// <param name="title">The title of the program (typically title screen title).</param>
 /// <param name="vendor">Vendor who wrote the program.</param>
 /// <param name="year">The year the program was copyrighted (or released).</param>
 /// <param name="crcData">The CRC values of known versions of the program.</param>
 /// <param name="crcDescriptions">The descriptions of the known versions of the program for each CRC.</param>
 /// <param name="generalFeatures">Generic program features.</param>
 /// <param name="cuttleCart3">Cuttle Cart 3 features.</param>
 internal UnmergedProgram(string code, string title, string vendor, string year, uint[] crcData, string[] crcDescriptions, GeneralFeatures generalFeatures, CuttleCart3Features cuttleCart3)
 {
     Code                     = code;
     CrcData                  = crcData;
     CrcDescriptions          = crcDescriptions;
     CrcCfgs                  = Enumerable.Repeat(-1, crcData.Count()).ToArray();
     Year                     = year;
     Title                    = title;
     Vendor                   = vendor;
     Features                 = new ProgramFeatures();
     Features.GeneralFeatures = generalFeatures;
     Features.CuttleCart3     = cuttleCart3;
 }
Example #2
0
 /// <summary>
 /// Creates a new instance if the UnmergedProgram structure.
 /// </summary>
 /// <param name="code">INTV Funhouse code for the ROM.</param>
 /// <param name="title">The title of the program (typically title screen title).</param>
 /// <param name="vendor">Vendor who wrote the program.</param>
 /// <param name="year">The year the program was copyrighted (or released).</param>
 /// <param name="crcData">The CRC values of known versions of the program.</param>
 /// <param name="crcDescriptions">The descriptions of the known versions of the program for each CRC.</param>
 /// <param name="generalFeatures">Generic program features.</param>
 /// <param name="intellivoice">Intellivoice compatibility.</param>
 internal UnmergedProgram(string code, string title, string vendor, string year, uint[] crcData, string[] crcDescriptions, GeneralFeatures generalFeatures, FeatureCompatibility intellivoice)
 {
     Code                     = code;
     CrcData                  = crcData;
     CrcDescriptions          = crcDescriptions;
     CrcCfgs                  = Enumerable.Repeat((generalFeatures == GeneralFeatures.SystemRom) ? -1 : 0, crcData.Count()).ToArray();
     Year                     = year;
     Title                    = title;
     Vendor                   = vendor;
     Features                 = new ProgramFeatures();
     Features.GeneralFeatures = generalFeatures;
     Features.Intellivoice    = intellivoice;
 }
Example #3
0
 /// <summary>
 /// Creates a new instance if the UnmergedProgram structure.
 /// </summary>
 /// <param name="code">INTV Funhouse code for the ROM.</param>
 /// <param name="title">The title of the program (typically title screen title).</param>
 /// <param name="vendor">Vendor who wrote the program.</param>
 /// <param name="year">The year the program was copyrighted (or released).</param>
 /// <param name="crcData">The CRC values of known versions of the program.</param>
 /// <param name="crcDescriptions">The descriptions of the known versions of the program for each CRC.</param>
 /// <param name="generalFeatures">Generic program features.</param>
 /// <param name="keyboardComponent">Keyboard component features.</param>
 internal UnmergedProgram(string code, string title, string vendor, string year, uint[] crcData, string[] crcDescriptions, GeneralFeatures generalFeatures, KeyboardComponentFeatures keyboardComponent)
 {
     Code                       = code;
     CrcData                    = crcData;
     CrcDescriptions            = crcDescriptions;
     CrcCfgs                    = Enumerable.Repeat(-1, crcData.Count()).ToArray();
     Year                       = year;
     Title                      = title;
     Vendor                     = vendor;
     Features                   = new ProgramFeatures();
     Features.GeneralFeatures   = generalFeatures;
     Features.KeyboardComponent = keyboardComponent;
 }
 /// <summary>
 /// Initializes a new instance of the <see cref="INTV.Core.Model.Program.LuigiFileMetadataProgramInformation"/> class.
 /// </summary>
 /// <param name="header">A LUIGI file header that describes the ROM's features.</param>
 /// <param name="metadata">Additional ROM metadata, if any.</param>
 public LuigiFileMetadataProgramInformation(LuigiFileHeader header, LuigiMetadataBlock metadata)
 {
     _features = ProgramFeatures.Combine(header.Features.ToProgramFeatures(), header.Features2.ToProgramFeatures());
     _crc      = new CrcData(header.OriginalRomCrc32, string.Empty, _features.ToIncompatibilityFlags());
     Metadata  = metadata;
     if (metadata != null)
     {
         _title  = metadata.LongNames.FirstOrDefault();
         _vendor = metadata.Publishers.FirstOrDefault();
         if (metadata.ReleaseDates.Any())
         {
             _year = metadata.ReleaseDates.First().Date.Year.ToString();
         }
         _shortName = metadata.ShortNames.FirstOrDefault();
     }
 }
Example #5
0
 /// <summary>
 /// Creates a new instance of the UnmergedProgramInformation class.
 /// </summary>
 /// <param name="code">INTV Funhouse database code of the program.</param>
 /// <param name="title">Title of the program.</param>
 /// <param name="vendor">Program vendor.</param>
 /// <param name="year">The year the program was copyrighted (or released).</param>
 /// <param name="crcData">Known CRC values for the program ROM variants.</param>
 /// <param name="crcDescriptions">Descriptions of the ROM variations.</param>
 /// <param name="crcCfgs">The default .cfg file to use if one is not provided.</param>
 /// <param name="features">The program's features.</param>
 internal UnmergedProgramInformation(string code, string title, string vendor, string year, uint[] crcData, string[] crcDescriptions, int[] crcCfgs, ProgramFeatures features)
 {
     Code    = code;
     _title  = title;
     _vendor = vendor;
     _year   = year;
     _crc    = new List <CrcData>();
     for (int i = 0; i < crcData.Length; ++i)
     {
         var crcDescription = string.Empty;
         if (i < crcDescriptions.Length)
         {
             crcDescription = crcDescriptions[i];
         }
         _crc.Add(new CrcData(crcData[i], crcDescription, IncompatibilityFlags.None, crcCfgs[i]));
     }
     _features = features;
 }
Example #6
0
        /// <summary>
        /// Initializes a new instance of the <see cref="INTV.Core.Model.Program.RomFileMetadataProgramInformation"/> class.
        /// </summary>
        /// <param name="rom">The ROM whose metadata program information is desired. If not a RomFormatRom, the
        /// metadata will be empty, and the features will be generic unrecognized ROM features.</param>
        public RomFileMetadataProgramInformation(IRom rom)
        {
            _features = ProgramFeatures.GetUnrecognizedRomFeatures();
            Metadata  = Enumerable.Empty <RomMetadataBlock>();
            var romFormatRom = Rom.AsSpecificRomType <RomFormatRom>(rom);

            if (romFormatRom != null)
            {
                Metadata = romFormatRom.Metadata;
                var stringMetaData = Metadata.FirstOrDefault(m => m.Type == RomMetadataIdTag.Title) as RomMetadataString;
                if ((stringMetaData != null) && !string.IsNullOrEmpty(stringMetaData.StringValue))
                {
                    _title = stringMetaData.StringValue;
                }
                stringMetaData = Metadata.FirstOrDefault(m => m.Type == RomMetadataIdTag.ShortTitle) as RomMetadataString;
                if ((stringMetaData != null) && !string.IsNullOrEmpty(stringMetaData.StringValue))
                {
                    _shortName = stringMetaData.StringValue;
                }
                var date = Metadata.OfType <RomMetadataDate>().FirstOrDefault(d => d.Type == RomMetadataIdTag.ReleaseDate);
                if ((date != null) && date.Date.Flags.HasFlag(MetadataDateTimeFlags.Year))
                {
                    _year = date.Date.Date.Year.ToString();
                }
                var vendor = Metadata.OfType <RomMetadataPublisher>().FirstOrDefault();
                if (vendor != null)
                {
                    _vendor = vendor.Publisher;
                }
                var features = Metadata.OfType <RomMetadataFeatures>().FirstOrDefault();
                if (features != null)
                {
                    _features = features.Features;
                }
                _crc = new CrcData(romFormatRom.Crc, string.Empty, _features.ToIncompatibilityFlags());
            }
        }
Example #7
0
        public CfgFileMetadataProgramInformation(IRom rom)
        {
            _features = ProgramFeatures.GetUnrecognizedRomFeatures();
            Metadata  = Enumerable.Empty <CfgVarMetadataBlock>();
            var binFormatRom = Rom.AsSpecificRomType <BinFormatRom>(rom);

            if (binFormatRom != null)
            {
                Metadata = binFormatRom.Metadata;
                var stringMetaData = Metadata.FirstOrDefault(m => m.Type == CfgVarMetadataIdTag.Name) as CfgVarMetadataString;
                if ((stringMetaData != null) && !string.IsNullOrEmpty(stringMetaData.StringValue))
                {
                    _title = stringMetaData.StringValue;
                }
                stringMetaData = Metadata.FirstOrDefault(m => m.Type == CfgVarMetadataIdTag.ShortName) as CfgVarMetadataString;
                if ((stringMetaData != null) && !string.IsNullOrEmpty(stringMetaData.StringValue))
                {
                    _shortName = stringMetaData.StringValue;
                }
                var date = Metadata.OfType <CfgVarMetadataDate>().FirstOrDefault(d => d.Type == CfgVarMetadataIdTag.ReleaseDate);
                if ((date != null) && date.Date.Flags.HasFlag(MetadataDateTimeFlags.Year))
                {
                    _year = date.Date.Date.Year.ToString();
                }
                var vendor = Metadata.FirstOrDefault(m => m.Type == CfgVarMetadataIdTag.Publisher) as CfgVarMetadataString;
                if (vendor != null)
                {
                    _vendor = vendor.StringValue;
                }

                // NOTE: If these are specified multiple times, the 'last one wins' rule will be in effect.
                // That's technically OK, since the behavior is unspecified. From as1600.txt:
                //
                // Lines marked with a "*" can be repeated.  For example, if a game has multiple
                // authors, you can list them all with their own author variable.  Likewise, if
                // a program was released multiple times, you can give a list of release dates.
                //
                // For other values, repeating a variable does not have a well defined meaning.
                // Typically (but not always), the first instance takes precedence.
                //
                // So in the case of specifying features multiple times, this code will result in
                // 'last one wins'.
                foreach (var feature in Metadata.OfType <CfgVarMetadataFeatureCompatibility>())
                {
                    switch (feature.Type)
                    {
                    case CfgVarMetadataIdTag.Ecs:
                    case CfgVarMetadataIdTag.EcsCompatibility:
                        _features.Ecs = (EcsFeatures)feature.Compatibility;
                        break;

                    case CfgVarMetadataIdTag.Voice:
                    case CfgVarMetadataIdTag.IntellivoiceCompatibility:
                        _features.Intellivoice = feature.Compatibility;
                        break;

                    case CfgVarMetadataIdTag.IntellivisionII:
                    case CfgVarMetadataIdTag.IntellivisionIICompatibility:
                        _features.IntellivisionII = feature.Compatibility;
                        break;

                    case CfgVarMetadataIdTag.KeyboardComponentCompatibility:
                        _features.KeyboardComponent = (KeyboardComponentFeatures)feature.Compatibility;
                        break;

                    case CfgVarMetadataIdTag.TutorvisionCompatibility:
                        _features.Tutorvision = feature.Compatibility;
                        break;

                    case CfgVarMetadataIdTag.JlpAccelerators:
                    case CfgVarMetadataIdTag.Jlp:
                        _features.Jlp = (JlpFeatures)feature.Compatibility;
                        if (_features.Jlp != JlpFeatures.Incompatible)
                        {
                            _features.JlpHardwareVersion = JlpHardwareVersion.Jlp03;     // Assume minimal hardware version needed
                            if (_features.Jlp > JlpFeatures.Tolerates)
                            {
                                // Flash storage is indicated, so check for it.
                                var flashStorage = Metadata.FirstOrDefault(m => m.Type == CfgVarMetadataIdTag.JlpFlash) as CfgVarMetadataInteger;
                                if ((flashStorage != null) && (flashStorage.IntegerValue > 0))
                                {
                                    // TODO: Min value checking here?
                                    _features.JlpFlashMinimumSaveSectors = (ushort)flashStorage.IntegerValue;
                                    _features.Jlp |= JlpFeatures.SaveDataRequired;
                                }
                            }
                        }
                        break;

                    default:
                        break;
                    }
                }
                var ltoMapper = Metadata.FirstOrDefault(m => m.Type == CfgVarMetadataIdTag.LtoFlashMapper) as CfgVarMetadataBoolean;
                if (ltoMapper != null)
                {
                    _features.LtoFlash = LtoFlashFeatures.Requires | LtoFlashFeatures.LtoFlashMemoryMapped;
                }
                _crc = new CrcData(binFormatRom.Crc, string.Empty, _features.ToIncompatibilityFlags());
            }
        }
Example #8
0
        /// <summary>
        /// Merges the given IProgramInformation data to form a new, combined version of the information.
        /// </summary>
        /// <param name="programInformation">The "primary" source of information.</param>
        /// <param name="fieldsToMerge">Identifies which fields to merge.</param>
        /// <param name="otherSources">The other information sources to merge, and how to merge them. See Remarks.</param>
        /// <returns>The merged program information.</returns>
        /// <remarks>Each of the additional information sources in the merge will be combined with the primary. The newly
        /// merged information is initialized using the data from <paramref name="programInformation"/>. The
        /// other sources should be ordered such that the first entry is the "most important" and the final entry the
        /// "least important". Each entry also describes which fields it is allowed to override in the merge.
        /// This is to offer a means of conflict resolution in situations arising from multiple sources containing
        /// the same information and attempting to override the default. For example, consider the case in which
        /// <paramref name="programInformation"/> and two entries are provided via <paramref name="otherSources"/>,
        /// all three of which define a value for <see cref="IProgramInformation.Title"/>. Here are some ways in which
        /// this can be configured:
        /// <code>
        /// fieldsToMerge = ProgramInformationMergeFieldsFlags.None;
        /// </code>
        /// In this case, the information in <paramref name="programInformation"/> will not be changed. A copy of the
        /// data within it will be returned. Note, however, that the specific implementation of <see cref="IProgramInformation"/>
        /// used to deliver the resulting data may be different than the original!
        /// Now, consider this scenario:
        /// <code>
        /// fieldsToMerge = ProgramInformationMergeFieldsFlags.Title;
        /// otherSources[0].Item2 = ProgramInformationMergeFieldsFlags.Title;
        /// otherSources[1].Item2 = ProgramInformationMergeFieldsFlags.Title;
        /// </code>
        /// In this case, each entry allows 'Title' to be set. Because <paramref name="programInformation"/> is
        /// treated as the highest priority, its value will be retained unless it is not set (in this case, a <c>null</c>
        /// or empty string). So, if programInformation.Title has no value, but otherSources[0].Item1.Title does, then
        /// the final result contains otherSources[0].Item1.Title, regardless of the value of otherSources[1].Item1.Title.
        /// By carefully considering these flags, you can have a reasonably rich order-of-precedence defined for establishing
        /// the data in the merged result.
        /// </remarks>
        /// <exception cref="System.ArgumentException">Thrown if unrecognized flags are provided in <paramref name="fieldsToMerge"/> or via <paramref name="otherSources"/>.</exception>
        public static IProgramInformation Merge(this IProgramInformation programInformation, ProgramInformationMergeFieldsFlags fieldsToMerge, params Tuple <IProgramInformation, ProgramInformationMergeFieldsFlags>[] otherSources)
        {
            // Grr.... PCLs (at least in .NET 4.0) don't support Enum.GetValues()
            var flagsToProcess = new[] { ProgramInformationMergeFieldsFlags.Title, ProgramInformationMergeFieldsFlags.Vendor, ProgramInformationMergeFieldsFlags.Year, ProgramInformationMergeFieldsFlags.Features, ProgramInformationMergeFieldsFlags.ShortName, ProgramInformationMergeFieldsFlags.Crcs };

            var unknownFlagsForMerge = otherSources.Select(s => s.Item2).Concat(new[] { fieldsToMerge }).Except(flagsToProcess).Except(new[] { ProgramInformationMergeFieldsFlags.None, ProgramInformationMergeFieldsFlags.All });

            if (unknownFlagsForMerge.Any())
            {
                var unknownFlags = unknownFlagsForMerge.Aggregate((all, flag) => all | flag);
                throw new ArgumentException(string.Format(Resources.Strings.ProgramInformation_InvalidFieldFormat, unknownFlags));
            }

            var mergedProgramInformation = new UserSpecifiedProgramInformation(programInformation);
            var mergedPriorityFlags      = fieldsToMerge; // accumulates if a "higher priority" info has already claimed a field

            foreach (var otherSource in otherSources)
            {
                var otherInformation = otherSource.Item1;
                var updateFlags      = otherSource.Item2;
                foreach (var flag in flagsToProcess)
                {
                    if (updateFlags.HasFlag(flag))
                    {
                        switch (flag)
                        {
                        case ProgramInformationMergeFieldsFlags.Title:
                            if (string.IsNullOrEmpty(mergedProgramInformation.Title) || !mergedPriorityFlags.HasFlag(flag))
                            {
                                mergedProgramInformation.Title = otherInformation.Title;
                                if (!string.IsNullOrEmpty(mergedProgramInformation.Title))
                                {
                                    mergedPriorityFlags |= flag;
                                }
                            }
                            break;

                        case ProgramInformationMergeFieldsFlags.Vendor:
                            if (string.IsNullOrEmpty(mergedProgramInformation.Vendor) || !mergedPriorityFlags.HasFlag(flag))
                            {
                                mergedProgramInformation.Vendor = otherInformation.Vendor;
                                if (!string.IsNullOrEmpty(mergedProgramInformation.Vendor))
                                {
                                    mergedPriorityFlags |= flag;
                                }
                            }
                            break;

                        case ProgramInformationMergeFieldsFlags.Year:
                            if (string.IsNullOrEmpty(mergedProgramInformation.Year) || !mergedPriorityFlags.HasFlag(flag))
                            {
                                mergedProgramInformation.Year = otherInformation.Year;
                                if (!string.IsNullOrEmpty(mergedProgramInformation.Year))
                                {
                                    mergedPriorityFlags |= flag;
                                }
                            }
                            break;

                        case ProgramInformationMergeFieldsFlags.Features:
                            // This runs the risk of combining conflicting flags...
                            mergedProgramInformation.Features = ProgramFeatures.Combine(mergedProgramInformation.Features, otherInformation.Features);
                            mergedPriorityFlags |= flag;
                            break;

                        case ProgramInformationMergeFieldsFlags.ShortName:
                            if (string.IsNullOrEmpty(mergedProgramInformation.ShortName) || !mergedPriorityFlags.HasFlag(flag))
                            {
                                mergedProgramInformation.ShortName = otherInformation.ShortName;
                                if (!string.IsNullOrEmpty(mergedProgramInformation.ShortName))
                                {
                                    mergedPriorityFlags |= flag;
                                }
                            }
                            break;

                        case ProgramInformationMergeFieldsFlags.Crcs:
                            var crcsToMerge = otherInformation.Crcs.Where(o => !mergedProgramInformation.Crcs.Any(m => m.Crc == o.Crc));
                            foreach (var crc in crcsToMerge)
                            {
                                mergedProgramInformation.AddCrc(crc.Crc, crc.Description, crc.Incompatibilities);
                                mergedPriorityFlags |= flag;
                            }
                            break;
                        }
                    }
                }
            }
            return(mergedProgramInformation);
        }
Example #9
0
 /// <summary>
 /// Updates a set of ProgramFeatures to include an incompatibilities set in the given flags.
 /// </summary>
 /// <param name="incompatibilityFlags">Condensed incompatibility information.</param>
 /// <param name="programFeatures">The program features to update.</param>
 /// <returns>The updated program features.</returns>
 public static ProgramFeatures ApplyFlagsToProgramFeatures(this IncompatibilityFlags incompatibilityFlags, ProgramFeatures programFeatures)
 {
     if ((incompatibilityFlags & IncompatibilityFlags.Ntsc) == IncompatibilityFlags.Ntsc)
     {
         programFeatures.Ntsc = FeatureCompatibility.Incompatible;
     }
     if ((incompatibilityFlags & IncompatibilityFlags.Pal) == IncompatibilityFlags.Pal)
     {
         programFeatures.Pal = FeatureCompatibility.Incompatible;
     }
     if ((incompatibilityFlags & IncompatibilityFlags.KeyboardComponent) == IncompatibilityFlags.KeyboardComponent)
     {
         programFeatures.KeyboardComponent = KeyboardComponentFeatures.Incompatible;
     }
     if ((incompatibilityFlags & IncompatibilityFlags.SuperVideoArcade) == IncompatibilityFlags.SuperVideoArcade)
     {
         programFeatures.SuperVideoArcade = FeatureCompatibility.Incompatible;
     }
     if ((incompatibilityFlags & IncompatibilityFlags.SuperVideoArcadeAltered) == IncompatibilityFlags.SuperVideoArcadeAltered)
     {
         programFeatures.SuperVideoArcade = FeatureCompatibility.Enhances;
     }
     if ((incompatibilityFlags & IncompatibilityFlags.Intellivoice) == IncompatibilityFlags.Intellivoice)
     {
         programFeatures.Intellivoice = FeatureCompatibility.Incompatible;
     }
     if ((incompatibilityFlags & IncompatibilityFlags.IntellivisionII) == IncompatibilityFlags.IntellivisionII)
     {
         programFeatures.IntellivisionII = FeatureCompatibility.Incompatible;
     }
     if ((incompatibilityFlags & IncompatibilityFlags.IntellivisionIIAltered) == IncompatibilityFlags.IntellivisionIIAltered)
     {
         programFeatures.IntellivisionII = FeatureCompatibility.Enhances;
     }
     if ((incompatibilityFlags & IncompatibilityFlags.Ecs) == IncompatibilityFlags.Ecs)
     {
         programFeatures.Ecs = EcsFeatures.Incompatible;
     }
     if ((incompatibilityFlags & IncompatibilityFlags.Tutorvision) == IncompatibilityFlags.Tutorvision)
     {
         programFeatures.Tutorvision = FeatureCompatibility.Incompatible;
     }
     if ((incompatibilityFlags & IncompatibilityFlags.Intellicart) == IncompatibilityFlags.Intellicart)
     {
         programFeatures.Intellicart = IntellicartCC3Features.Incompatible;
     }
     if ((incompatibilityFlags & IncompatibilityFlags.CuttleCart3) == IncompatibilityFlags.CuttleCart3)
     {
         programFeatures.CuttleCart3 = CuttleCart3Features.Incompatible;
     }
     if ((incompatibilityFlags & IncompatibilityFlags.Jlp) == IncompatibilityFlags.Jlp)
     {
         programFeatures.Jlp = JlpFeatures.Incompatible;
     }
     if ((incompatibilityFlags & IncompatibilityFlags.LtoFlash) == IncompatibilityFlags.LtoFlash)
     {
         programFeatures.LtoFlash = LtoFlashFeatures.Incompatible;
     }
     if ((incompatibilityFlags & IncompatibilityFlags.Bee3) == IncompatibilityFlags.Bee3)
     {
         programFeatures.Bee3 = Bee3Features.Incompatible;
     }
     if ((incompatibilityFlags & IncompatibilityFlags.Hive) == IncompatibilityFlags.Hive)
     {
         programFeatures.Hive = HiveFeatures.Incompatible;
     }
     return(programFeatures);
 }
Example #10
0
        /// <summary>
        /// Expands a set of condensed incompatibility flags to a full-fledged ProgramFeatures set.
        /// </summary>
        /// <param name="incompatibilityFlags">The flags to convert.</param>
        /// <returns>A ProgramFeatures object that includes all incompatibilities.</returns>
        /// <remarks>The default features are contained in the returned features for any incompatibility flag that is not set.</remarks>
        public static IProgramFeatures ToProgramFeatures(this IncompatibilityFlags incompatibilityFlags)
        {
            var programFeatures = new ProgramFeatures();

            return(incompatibilityFlags.ApplyFlagsToProgramFeatures(programFeatures));
        }
 /// <summary>
 /// Creates a new instance of the UserSpecifiedProgramInformation class.
 /// </summary>
 /// <param name="crc">The CRC of the program's ROM file.</param>
 /// <param name="title">The title of the program.</param>
 /// <param name="year">Copyright date of the program.</param>
 /// <param name="features">The features of the program.</param>
 /// <param name="crcDescription">Description of the variant of the program identified by its CRC.</param>
 /// <exception cref="ArgumentException">Thrown if crc is zero.</exception>
 /// <exception cref="ArgumentNullException">Thrown if any metadata values are <c>null</c>.</exception>
 public UserSpecifiedProgramInformation(uint crc, string title, string year, ProgramFeatures features, string crcDescription)
     : this(crc, title, year, features, crcDescription, IncompatibilityFlags.None)
 {
 }
 /// <summary>
 /// Creates a new instance of the UserSpecifiedProgramInformation class.
 /// </summary>
 /// <param name="crc">The CRC of the program's ROM file.</param>
 /// <param name="title">The title of the program.</param>
 /// <param name="year">Copyright date of the program.</param>
 /// <param name="features">The features of the program.</param>
 /// <exception cref="ArgumentException">Thrown if crc is zero.</exception>
 public UserSpecifiedProgramInformation(uint crc, string title, string year, ProgramFeatures features)
     : this(crc, title, year, features, string.Empty)
 {
 }
 /// <summary>
 /// Creates a new instance of the UserSpecifiedProgramInformation class.
 /// </summary>
 /// <param name="crc">The CRC of the program's ROM file.</param>
 /// <param name="title">The title of the program.</param>
 /// <param name="year">Copyright date of the program.</param>
 /// <exception cref="ArgumentException">Thrown if crc is zero.</exception>
 public UserSpecifiedProgramInformation(uint crc, string title, string year)
     : this(crc, title, year, ProgramFeatures.GetUnrecognizedRomFeatures())
 {
 }
Example #14
0
 /// <inheritdoc />
 public bool Equals(ProgramFeatures other)
 {
     return(CompareTo(other) == 0);
 }
Example #15
0
        /// <summary>
        /// Combines two sets of ProgramFeatures into a new set of ProgramFeatures.
        /// </summary>
        /// <param name="features1">The first set of features.</param>
        /// <param name="features2">The second set of features.</param>
        /// <returns>The combined set of features.</returns>
        /// <remarks>NOTE: Only basic consistency checks are done. The default behavior is to OR the feature bits of each category
        /// together, with additional comparison against the default set of bits for the feature set. If the bits are different from
        /// each other, and one set matches the default bits while the other does not, then the non-default bits "win".
        /// If both feature sets define a JLP Hardware version, the larger of the two versions is used.</remarks>
        public static ProgramFeatures Combine(ProgramFeatures features1, ProgramFeatures features2)
        {
            ProgramFeatures combinedFeatures = null;

            if ((features1 == null) && (features2 == null))
            {
                combinedFeatures = GetUnrecognizedRomFeatures();
            }
            else if (features1 == null)
            {
                combinedFeatures = features2.Clone();
            }
            else if (features2 == null)
            {
                combinedFeatures = features1.Clone();
            }
            else
            {
                combinedFeatures = EmptyFeatures.Clone();
                foreach (var feature in features1._features.Keys)
                {
                    var defaultFeatureBits        = DefaultFeatures._features[feature];
                    var features1Bits             = features1._features[feature];
                    var features2Bits             = features2._features[feature];
                    var features1BitsMatchDefault = features1Bits == defaultFeatureBits;
                    var features2BitsMatchDefault = features2Bits == defaultFeatureBits;
                    var featureBits = features1Bits;
                    if (features1BitsMatchDefault && !features2BitsMatchDefault)
                    {
                        featureBits = features2Bits;
                    }
                    else if (features2BitsMatchDefault && !features1BitsMatchDefault)
                    {
                        featureBits = features1Bits;
                    }
                    else if (!features1BitsMatchDefault && !features2BitsMatchDefault)
                    {
                        featureBits = features1Bits | features2Bits;
                    }
                    switch (feature)
                    {
                    case FeatureCategory.Ntsc:
                    case FeatureCategory.Pal:
                        // If we've combined "Tolerates" and "Enhances" we'll get "required", which, for video standards, is not suitable.
                        featureBits = (uint)((FeatureCompatibility)featureBits).CoerceVideoStandardCompatibility();
                        break;

                    case FeatureCategory.General:
                    case FeatureCategory.SuperVideoArcade:
                        // Leave these alone...
                        break;

                    default:
                        // For these, we don't want to have a 'tolerates' combine with 'enhances' to turn into 'requires', so, if
                        // one set contains only 'tolerates' and the other contains only 'enhances' then just keep 'enhances'.
                        var feature1Compat = features1Bits & FeatureCompatibilityHelpers.CompatibilityMask;
                        var feature2Compat = features2Bits & FeatureCompatibilityHelpers.CompatibilityMask;
                        if ((feature1Compat != 0) && (feature2Compat != 0) && ((feature1Compat ^ feature2Compat) == (uint)FeatureCompatibility.Requires))
                        {
                            // Retain 'enhances' only.
                            featureBits &= (uint)~FeatureCompatibility.Tolerates;
                        }
                        break;
                    }
                    combinedFeatures.CheckAccessSetFeatureBits(feature, featureBits);
                }
                combinedFeatures.JlpHardwareVersion = (JlpHardwareVersion)Math.Max((int)features1.JlpHardwareVersion, (int)features2.JlpHardwareVersion);
            }
            return(combinedFeatures);
        }