/// <inheritdoc /> public override int Compare(IRom x, IProgramInformation programInformationRomX, IRom y, IProgramInformation programInformationRomY) { var result = base.Compare(x, programInformationRomX, y, programInformationRomY); if ((result == 0) && (x != null)) { switch (x.Format) { case RomFormat.Bin: result = CheckCrcs(x, programInformationRomX, y, programInformationRomY); break; case RomFormat.Luigi: result = CheckCrcs(x, programInformationRomX, y, programInformationRomY); if ((result == 0) && (y.Format == RomFormat.Luigi)) { // It's possible LUIGI files' original CRCs match, but the LUIGI files themselves do not. // This once occurred when additional bytes were somehow appended to a downloaded LUIGI. In // that case, all the CRC data matched, so even the "strict" CRC check, which compared the // full 8 bytes of the ID in the header, still matched. However, the additional data at the // end of the corrupted file resulted in failure to load on LTO Flash! hardware. Therefore, // when comparing what appear to be two identical LUIGI files, still compare full file CRCs. result = (int)(Rom.AsSpecificRomType <LuigiFormatRom>(x).Crc24 - Rom.AsSpecificRomType <LuigiFormatRom>(y).Crc24); } break; default: break; } } return(result); }
/// <summary> /// Gets IProgramInformation from a LUIGI file's metadata, if it is available. /// </summary> /// <param name="rom">The ROM from which metadata-based information is retrieved.</param> /// <returns>IProgramInformation retrieved from the LUIGI format ROM.</returns> public static LuigiFileMetadataProgramInformation GetLuigiFileMetadata(this IRom rom) { LuigiFileMetadataProgramInformation programInfo = null; var luigiRom = Rom.AsSpecificRomType <LuigiFormatRom>(rom); if (luigiRom != null) { try { var metadata = luigiRom.LocateDataBlock <LuigiMetadataBlock>(); if (metadata != null) { programInfo = new LuigiFileMetadataProgramInformation(luigiRom.Header, metadata); } } catch (Exception e) { // We don't really want to raise a lot of trouble if this is somehow wrong... Perhaps we should report this more aggressively // if it happens in the field, but for now, quietly fail. System.Diagnostics.Debug.WriteLine("Failed to get LUIGI metadata. Error: " + e.Message); #if DEBUG throw; #endif // DEBUG } } return(programInfo); }
/// <summary> /// Gets the unique ID of the device for which a ROM may be targeted, if applicable. /// </summary> /// <param name="rom">The ROM whose target's unique ID is desired.</param> /// <returns>The ROM target device's unique identifier. If the ROM is not targeted to a /// general category of peripheral (e.g. LTO Flash!), or a specific device, the return /// value is <c>null</c>.</returns> public static string GetTargetDeviceUniqueId(this IRom rom) { var luigiRom = Rom.AsSpecificRomType <LuigiFormatRom>(rom); var uniqueId = (luigiRom != null) ? luigiRom.TargetDeviceUniqueId : null; return(uniqueId); }
/// <summary> /// Determines if the ROM will only run on LTO Flash! hardware. /// </summary> /// <param name="rom">The ROM to check.</param> /// <returns><c>true</c> if the ROM only runs on LTO Flash! hardware; otherwise, <c>false</c>.</returns> /// <remarks>Only LUIGI format ROMs are currently known to support this capability. Any LUIGI-format /// ROM that contains a 'scramble key' block is considered LTO Flash!-only. Three categories of /// behavior are currently defined: /// 1) ROM runs anywhere; if ROM is in LUIGI format, target must understand it; .bin and .rom formats are considered universally supported /// 2) ROM runs on any LTO Flash! device; /// 3) ROM runs only on a specific LTO Flash! device.</remarks> public static bool IsLtoFlashOnlyRom(this IRom rom) { var luigiRom = Rom.AsSpecificRomType <LuigiFormatRom>(rom); var isLtoFlashOnly = (luigiRom != null) && !string.IsNullOrEmpty(luigiRom.TargetDeviceUniqueId); return(isLtoFlashOnly); }
/// <summary> /// Determines if the given ROM can execute on a specific device that has the given <paramref name="deviceUniqueId"/>. /// </summary> /// <param name="rom">The ROM to check.</param> /// <param name="deviceUniqueId">The unique device identifier to use to determine if the ROM can execute upon it.</param> /// <returns><c>true</c> if the ROM can execute on device identified by <paramref name="deviceUniqueId"/>; otherwise, <c>false</c>.</returns> /// <remarks>By default, all non-LUIGI-format ROMs are assumed to be executable on any device. If <paramref name="rom"/> /// is a LUIGI-format ROM, and only runs on LTO Flash!, then the following rules apply: /// 1) If no scramble key block is present, the ROM will execute, regardless of the value if <paramref name="deviceUniqueId"/> /// 2) If a scramble key block is present, but the TargetDeviceUniqueId contained within it is <see cref="LuigiScrambleKeyBlock.AnyLTOFlashId"/>, the ROM will execute /// 3) If a scramble key block is present, the ROM is executable only if the ROM's scramble key block contains a TargetDeviceUniqueId that matches <paramref name="deviceUniqueId"/>.</remarks> public static bool CanExecuteOnDevice(this IRom rom, string deviceUniqueId) { var canExecuteOnDevice = true; if ((rom != null) && !string.IsNullOrEmpty(deviceUniqueId)) { var luigiRom = Rom.AsSpecificRomType <LuigiFormatRom>(rom); if (luigiRom != null) { var targetDeviceId = luigiRom.TargetDeviceUniqueId; canExecuteOnDevice = string.IsNullOrEmpty(targetDeviceId) || targetDeviceId.Equals(LuigiScrambleKeyBlock.AnyLTOFlashId) || targetDeviceId.Equals(deviceUniqueId); } } return(canExecuteOnDevice); }
/// <summary> /// Gets IProgramInformation from a .ROM-format file's metadata, if it is available. /// </summary> /// <param name="rom">The ROM from which metadata-based information is retrieved.</param> /// <returns>IProgramInformation retrieved from the .ROM-format ROM.</returns> public static RomFileMetadataProgramInformation GetRomFileMetadata(this IRom rom) { RomFileMetadataProgramInformation programInfo = null; var romRom = Rom.AsSpecificRomType <RomFormatRom>(rom); if (romRom != null) { programInfo = new RomFileMetadataProgramInformation(rom); if (!programInfo.Metadata.Any()) { programInfo = null; } } return(programInfo); }
/// <summary> /// Gets IProgramInformation from a .BIN-format file's metadata, if it is available. /// </summary> /// <param name="rom">The ROM from which metadata-based information is retrieved.</param> /// <returns>IProgramInformation retrieved from the .BIN-format ROM's .cfg file.</returns> public static CfgFileMetadataProgramInformation GetBinFileMetadata(this IRom rom) { CfgFileMetadataProgramInformation programInfo = null; var binRom = Rom.AsSpecificRomType <BinFormatRom>(rom); if (binRom != null) { programInfo = new CfgFileMetadataProgramInformation(rom); if (!programInfo.Metadata.Any()) { programInfo = null; } } return(programInfo); }
/// <summary> /// Gets the original <see cref="IRom"/> referred to by <paramref name="rom"/>. /// </summary> /// <param name="rom">The ROM whose original is desired.</param> /// <returns>The original ROM. Unless <paramref name="rom"/> refers to a ROM located on external devices, and that device is not accessible, this is usually just <paramref name="rom"/>.</returns> public static IRom OriginalRom(this IRom rom) { var originalRom = rom; var alternateRom = Rom.AsSpecificRomType <AlternateRom>(rom); if (alternateRom != null) { originalRom = alternateRom.Original; } else { var xmlRom = Rom.AsSpecificRomType <XmlRom>(rom); if (xmlRom != null) { originalRom = xmlRom.ResolvedRom; } } return(originalRom); }