private static bool ShouldRemoveSecondaryFirmware(this Device device, ExecuteDeviceCommandAsyncTaskData taskData, out bool succeeded) { var firmwareRevisions = QueryFirmwareRevisions.Instance.Execute(device.Port, taskData, out succeeded) as FirmwareRevisions; var shouldRemove = succeeded && (firmwareRevisions.Secondary != FirmwareRevisions.UnavailableFirmwareVersion); return(shouldRemove); }
private static LuigiFileHeader GetLuigiHeaderForFork(ExecuteDeviceCommandAsyncTaskData data, Fork fork) { LuigiFileHeader luigiHeader = null; using (var memory = new System.IO.MemoryStream()) { const uint Address = 0u; var bytesToRead = LuigiFileHeader.MaxHeaderSize; var succeeded = ReadForkToRam.Create(Address, fork.GlobalForkNumber, 0u, bytesToRead).Execute <bool>(data.Device.Port, data); byte[] dataRead = null; if (succeeded) { dataRead = (byte[])DownloadDataBlockFromRam.Create(Address, bytesToRead).Execute(data.Device.Port, data, out succeeded); } if (succeeded) { memory.Write(dataRead, 0, bytesToRead); memory.Seek(0, System.IO.SeekOrigin.Begin); try { luigiHeader = LuigiFileHeader.Inflate(memory); } catch (INTV.Core.UnexpectedFileTypeException) { } } } return(luigiHeader); }
private static object RemoveSecondaryFirmware(this Device device, ExecuteDeviceCommandAsyncTaskData taskData, out bool succeeded) { var result = EraseSecondaryFirmware.Instance.Execute(device.Port, taskData, out succeeded); if (succeeded) { device.WaitForBeacon(ProtocolCommand.WaitForBeaconTimeout * 2); } return(result); }
/// <summary> /// Retrieves the data associated with forks from a Locutus device. /// </summary> /// <param name="device">The device upon which the data resides.</param> /// <param name="forksToRetrieve">The data forks to retrieve.</param> public static void RetrieveForkData(this Device device, IEnumerable <Fork> forksToRetrieve) { if (forksToRetrieve.Any() && device.IsSafeToStartCommand()) { var executeCommandTaskData = new ExecuteDeviceCommandAsyncTaskData(device, ProtocolCommandId.MultistagePseudoCommand) { Data = forksToRetrieve }; executeCommandTaskData.StartTask(RetrieveForkData); } }
/// <summary> /// Gets the file system dirty flags from a Locutus device. /// </summary> /// <param name="device">The target Locutus device whose file system dirty flags are to be retrieved.</param> /// <param name="errorHandler">Error handler, used to report errors to the user.</param> public static void GetFileSystemFlags(this Device device, DeviceCommandErrorHandler errorHandler) { if (device.IsSafeToStartCommand()) { var executeCommandTaskData = new ExecuteDeviceCommandAsyncTaskData(device, ProtocolCommandId.LfsGetFileSystemStatusFlags) { OnSuccess = (c, p, r) => device.FileSystemFlags = (LfsDirtyFlags)r, OnFailure = errorHandler }; executeCommandTaskData.StartTask(GetFileSystemFlags); } }
/// <summary> /// Remove the secondary firmware from the device (i.e. revert to factory version.). /// </summary> /// <param name="device">Target of the command.</param> /// <param name="onCompleteHandler">Called upon successful completion of the operation. This argument may be <c>null</c>.</param> /// <param name="errorHandler">Error handler, used to report errors to the user.</param> public static void RemoveSecondaryFirmware(this Device device, DeviceCommandCompleteHandler onCompleteHandler, DeviceCommandErrorHandler errorHandler) { if (device.IsSafeToStartCommand()) { var executeCommandTaskData = new ExecuteDeviceCommandAsyncTaskData(device, ProtocolCommandId.FirmwareEraseSecondary) { OnSuccess = (c, p, r) => device.GetFirmwareRevisions(onCompleteHandler, errorHandler), OnFailure = errorHandler }; executeCommandTaskData.StartTask(RemoveSecondaryFirmware); } }
/// <summary> /// Updates the device configuration settings. /// </summary> /// <param name="device">The target Locutus device whose configuration is to be set.</param> /// <param name="newConfigurationFlags">The new configuration data.</param> /// <param name="onCompleteHandler">Success handler, used to report successful execution of the command.</param> /// <param name="errorHandler">Error handler, used to report errors to the user.</param> public static void SetConfiguration(this Device device, DeviceStatusFlags newConfigurationFlags, DeviceCommandCompleteHandler onCompleteHandler, DeviceCommandErrorHandler errorHandler) { if (device.IsSafeToStartCommand()) { var executeCommandTaskData = new ExecuteDeviceCommandAsyncTaskData(device, ProtocolCommandId.SetConfiguration) { Data = newConfigurationFlags, OnSuccess = onCompleteHandler, OnFailure = errorHandler }; executeCommandTaskData.StartTask(SetConfiguration); } }
/// <summary> /// Update firmware on the device. /// </summary> /// <param name="device">Target of the command.</param> /// <param name="firmwarePath">Path on local file system to the firmware update.</param> /// <param name="newVersion">New version of the firmware, used for validation.</param> /// <param name="onCompleteHandler">Called upon successful completion of the operation. This argument may be <c>null</c>.</param> /// <param name="errorHandler">Error handler, used to report errors to the user.</param> public static void UpdateFirmware(this Device device, string firmwarePath, int newVersion, DeviceCommandCompleteHandler onCompleteHandler, DeviceCommandErrorHandler errorHandler) { if (device.IsSafeToStartCommand()) { var data = new Tuple <string, int>(firmwarePath, newVersion); var executeCommandTaskData = new ExecuteDeviceCommandAsyncTaskData(device, ProtocolCommandId.MultistagePseudoCommand) { Title = Resources.Strings.DeviceMultistageCommand_UpdateFirmware_Title, Data = data, OnSuccess = (c, p, r) => device.GetFirmwareRevisions(onCompleteHandler, errorHandler), OnFailure = errorHandler }; executeCommandTaskData.StartTask(UpdateFirmware, 0.55); } }
/// <summary> /// Sets the device's owner. /// </summary> /// <param name="device">The device whose owner is to be set.</param> /// <param name="newOwner">The new owner for the device.</param> /// <param name="errorHandler">Error handler to report any problems.</param> public static void UpdateDeviceOwner(this Device device, string newOwner, DeviceCommandErrorHandler errorHandler) { if (device.IsSafeToStartCommand()) { var executeCommandTaskData = new ExecuteDeviceCommandAsyncTaskData(device, ProtocolCommandId.MultistagePseudoCommand) { Title = Resources.Strings.DeviceMultistageCommand_UpdateDeviceOwner_Title, FailureMessage = Resources.Strings.SetDeviceOwnerCommand_ErrorMessage, OnFailure = errorHandler, OnSuccess = (c, p, r) => device.Owner = newOwner, Data = newOwner }; executeCommandTaskData.StartTask(UpdateDeviceOwner); } }
/// <summary> /// Downloads a ROM to Locutus to be executed immediately. /// </summary> /// <param name="device">The target Locutus device to receive and execute the given ROM.</param> /// <param name="programRom">The ROM to play.</param> /// <param name="programName">The friendly name of the program to run.</param> /// <param name="errorHandler">Error handler, used to report errors to the user.</param> public static void DownloadAndPlay(this Device device, IRom programRom, string programName, DeviceCommandErrorHandler errorHandler) { if (device.IsSafeToStartCommand()) { var executeCommandTaskData = new ExecuteDeviceCommandAsyncTaskData(device, ProtocolCommandId.DownloadAndPlay) { Title = string.Format(Resources.Strings.DeviceCommand_DownloadAndPlay_TitleFormat, programName), ProgressUpdateMode = ExecuteDeviceCommandProgressUpdateMode.Custom, FailureMessage = string.Format(Resources.Strings.DeviceCommand_DownloadAndPlay_FailedFormat, programName), OnFailure = errorHandler, Data = programRom }; executeCommandTaskData.StartTask(DownloadAndPlay); } }
/// <summary> /// Executes a backup of the file system on a Locutus device. /// </summary> /// <param name="device">The device whose data is to be backed up.</param> /// <param name="backupDirectory">The directory in which to do the backup.</param> /// <param name="onCompleteHandler">Called upon successful completion of the operation. This argument may be <c>null</c>.</param> /// <param name="errorHandler">Function to call if an error occurs. If it returns <c>true</c>, the error is considered handled</param> public static void BackupFileSystem(this Device device, string backupDirectory, DeviceCommandCompleteHandler onCompleteHandler, DeviceCommandErrorHandler errorHandler) { if (device.IsSafeToStartCommand()) { var executeCommandTaskData = new ExecuteDeviceCommandAsyncTaskData(device, ProtocolCommandId.MultistagePseudoCommand) { Title = Resources.Strings.DeviceMultistageCommand_BackupFileSystem_Title, ProgressUpdateMode = ExecuteDeviceCommandProgressUpdateMode.Custom, Data = backupDirectory, OnSuccess = onCompleteHandler, OnFailure = errorHandler }; executeCommandTaskData.StartTask(BackupFileSystem, true, 0.5); } }
private static string GetSourcePathForFork(ExecuteDeviceCommandAsyncTaskData data, Fork fork, FileSystem deviceFileSystem, IEnumerable <ProgramDescription> roms, RomListConfiguration romsConfiguration) { bool retrievalNecessary; string destinationDir = null; var forkSourcePath = GetPathForFork(data, fork, deviceFileSystem, roms, romsConfiguration, ref destinationDir, out retrievalNecessary); if (retrievalNecessary) { if (!data.Device.RetrieveForkData(data, new[] { fork }, destinationDir, new[] { System.IO.Path.GetFileName(forkSourcePath) })) { var syncErrors = data.Result as FileSystemSyncErrors; syncErrors.UnableToRetrieveForks.Add(fork); forkSourcePath = null; } } return(forkSourcePath); }
/// <summary> /// Synchronizes the host system's MenuLayout to match the contents of a Locutus device. /// </summary> /// <param name="device">The Locutus device whose file system is to be imposed upon the Menu Layout of the host PC.</param> /// <param name="hostMenuLayout">The host PC MenuLayout to be brought in sync with Locutus.</param> /// <param name="ignoreInconsistentFileSystem">If <c>true</c> and the device's file system is in an inconsistent state, do the sync anyway.</param> /// <param name="onCompleteHandler">Called upon successful completion of the operation. This argument may be <c>null</c>.</param> /// <param name="errorHandler">Error handler, used to report errors to the user.</param> public static void SyncDeviceToHost(this Device device, MenuLayout hostMenuLayout, bool ignoreInconsistentFileSystem, DeviceCommandCompleteHandler onCompleteHandler, DeviceCommandErrorHandler errorHandler) { if (device.IsSafeToStartCommand()) { ////var configuration = SingleInstanceApplication.Instance.GetConfiguration<Configuration>(); var customData = new Tuple <MenuLayout, bool>(hostMenuLayout, ignoreInconsistentFileSystem); var executeCommandTaskData = new ExecuteDeviceCommandAsyncTaskData(device, ProtocolCommandId.MultistagePseudoCommand) { Title = Resources.Strings.DeviceMultistageCommand_SyncingToFiles_Title, ProgressUpdateMode = ExecuteDeviceCommandProgressUpdateMode.Custom, Data = customData, OnSuccess = onCompleteHandler, OnFailure = errorHandler }; executeCommandTaskData.StartTask(SyncDeviceToHost, true, 1); } }
/// <summary> /// Downloads the host system's MenuLayout file system content to a Locutus device. /// </summary> /// <param name="device">The target Locutus device whose file system is to be updated to match that of the host PC.</param> /// <param name="hostMenuLayout">The host PC MenuLayout to push down to Locutus.</param> /// <param name="onCompleteHandler">Called upon successful completion of the operation. This argument may be <c>null</c>.</param> /// <param name="errorHandler">Error handler, used to report errors to the user.</param> public static void SyncHostToDevice(this Device device, MenuLayout hostMenuLayout, DeviceCommandCompleteHandler onCompleteHandler, DeviceCommandErrorHandler errorHandler) { if (device.IsSafeToStartCommand()) { var executeCommandTaskData = new ExecuteDeviceCommandAsyncTaskData(device, ProtocolCommandId.MultistagePseudoCommand) { Title = Resources.Strings.DeviceMultistageCommand_UpdatingFiles_Title, ProgressUpdateMode = ExecuteDeviceCommandProgressUpdateMode.Custom, // First bool is whether to reset menu position data (true => REMOVE IT). // Second bool is whether to update root file name (false => RETAIN IT). Data = new Tuple <MenuLayout, bool, bool>(hostMenuLayout, true, false), OnSuccess = onCompleteHandler, OnFailure = errorHandler }; executeCommandTaskData.StartTask(SyncHostToDevice, true, 1); } }
public static void GetErrorLog(this Device device, Action <ErrorLog> onCompleteHandler, DeviceCommandErrorHandler errorHandler) { if (device.IsSafeToStartCommand()) { var executeCommandTaskData = new ExecuteDeviceCommandAsyncTaskData(device, ProtocolCommandId.DownloadErrorLog) { OnSuccess = (c, p, r) => { device.ErrorLog = (ErrorLog)r; if (onCompleteHandler != null) { onCompleteHandler(device.ErrorLog); } }, OnFailure = errorHandler }; executeCommandTaskData.StartTask(GetErrorLog); } }
/// <summary> /// Get the factory, active, and secondary firmware versions. /// </summary> /// <param name="device">Target of the command.</param> /// <param name="onCompleteHandler">Called upon successful completion of the operation. This argument may be <c>null</c>.</param> /// <param name="errorHandler">Error handler, used to report errors to the user.</param> public static void GetFirmwareRevisions(this Device device, DeviceCommandCompleteHandler onCompleteHandler, DeviceCommandErrorHandler errorHandler) { if (device.IsSafeToStartCommand()) { var executeCommandTaskData = new ExecuteDeviceCommandAsyncTaskData(device, ProtocolCommandId.FirmwareGetRevisions) { OnSuccess = (c, p, r) => { device.FirmwareRevisions = (FirmwareRevisions)r; if (onCompleteHandler != null) { onCompleteHandler(c, p, r); } }, OnFailure = errorHandler }; executeCommandTaskData.StartTask(GetFirmwareRevisions); } }
private static string GetRomPathForForkFromRomList(ExecuteDeviceCommandAsyncTaskData data, Fork fork, IEnumerable <ProgramDescription> roms, string destDir, out uint crc32, out uint cfgCrc32) { string romPath = null; crc32 = 0; cfgCrc32 = 0; var luigiHeader = GetLuigiHeaderForFork(data, fork); if ((luigiHeader != null) && (luigiHeader.Version > 0)) { crc32 = luigiHeader.OriginalRomCrc32; cfgCrc32 = luigiHeader.OriginalCfgCrc32; var rom = roms.FirstOrDefault(r => (r.Crc == luigiHeader.OriginalRomCrc32) && ((luigiHeader.OriginalCfgCrc32 == 0) || (luigiHeader.OriginalCfgCrc32 == r.Rom.CfgCrc))); if (rom != null) { romPath = rom.Rom.RomPath; } } return(romPath); }
/// <summary> /// Retrieves the file system from a Locutus device. /// </summary> /// <param name="device">The device whose file system is being retrieved.</param> /// <param name="operationTitle">Title to show in the progress bar.</param> /// <param name="onCompleteHandler">Called upon successful completion of the operation. This argument may be <c>null</c>.</param> /// <param name="errorHandler">Error handler, used to report errors to the user.</param> public static void RetrieveFileSystem(this Device device, string operationTitle, DeviceCommandCompleteHandler onCompleteHandler, DeviceCommandErrorHandler errorHandler) { if (device.IsSafeToStartCommand()) { var executeCommandTaskData = new ExecuteDeviceCommandAsyncTaskData(device, ProtocolCommandId.LfsDownloadGlobalTables) { Title = operationTitle, OnFailure = errorHandler }; executeCommandTaskData.OnSuccess = (c, p, r) => { device.FileSystem = (FileSystem)r; if (onCompleteHandler != null) { onCompleteHandler(c, p, r); } }; executeCommandTaskData.StartTask(RetrieveFileSystem, 1.5); } }
/// <summary> /// Reformats the file system on a Locutus device. /// </summary> /// <param name="device">The target Locutus device whose file system is to be reformatted.</param> /// <param name="errorHandler">Error handler, used to report errors to the user.</param> /// <param name="onComplete">Action to execute when reformat operation is complete. This value may be <c>null</c>.</param> public static void ReformatFileSystem(this Device device, DeviceCommandErrorHandler errorHandler, Action onComplete) { if (device.IsSafeToStartCommand()) { var reformatFileSystemTaskData = new ExecuteDeviceCommandAsyncTaskData(device, ProtocolCommandId.LfsReformatFileSystem) { OnSuccess = (c, p, r) => { var results = (Tuple <FileSystem, FileSystemStatistics>)r; device.FileSystem = results.Item1; device.FileSystemStatistics = results.Item2; if (onComplete != null) { onComplete(); } }, OnFailure = errorHandler }; reformatFileSystemTaskData.StartTask(ReformatFileSystem); } }
/// <summary> /// Retrieves the error and crash logs as needed from the target device. /// </summary> /// <param name="device">Target of the command.</param> /// <param name="onCompleteHandler">Called upon successful completion of the operation. This argument may be <c>null</c>.</param> /// <param name="errorHandler">Error handler, used to report errors to the user.</param> public static void GetErrorAndCrashLogs(this Device device, Action <ErrorLog, CrashLog> onCompleteHandler, DeviceCommandErrorHandler errorHandler) { if (device.IsSafeToStartCommand()) { var executeCommandTaskData = new ExecuteDeviceCommandAsyncTaskData(device, ProtocolCommandId.MultistagePseudoCommand) { Title = Resources.Strings.DeviceMultistageCommand_GetErrorAndCrashLogs_Title, OnSuccess = (c, p, r) => { var results = (Tuple <ErrorLog, CrashLog>)r; if (onCompleteHandler != null) { onCompleteHandler(results.Item1, results.Item2); } device.ErrorLog = results.Item1; device.CrashLog = results.Item2; }, OnFailure = errorHandler }; executeCommandTaskData.StartTask(GetErrorAndCrashLogs); } }
/// <summary> /// Initializes a new instance of FileSystemOperationData. /// </summary> /// <param name="operation">The kind of operation being performed.</param> /// <param name="taskData">Task data used for error reporting, et. al.</param> protected FileSystemOperationData(LfsOperations operation, ExecuteDeviceCommandAsyncTaskData taskData) { Operation = operation; TaskData = taskData; }
private static bool RetrieveForkData(this Device device, ExecuteDeviceCommandAsyncTaskData data, IEnumerable <Fork> forksToRetrieve, string destinationDirectory, IEnumerable <string> fileNames) { var configuration = SingleInstanceApplication.Instance.GetConfiguration <Configuration>(); var succeeded = false; var numForks = forksToRetrieve.Count(); var forkFilenames = fileNames == null ? null : fileNames.ToList(); var forkBeingRetrieved = 0; foreach (var fork in forksToRetrieve) { if (data.AcceptCancelIfRequested()) { break; } ++forkBeingRetrieved; if (data != null) { data.UpdateTaskProgress((double)forkBeingRetrieved / numForks, string.Format(Resources.Strings.DeviceMultistageCommand_BackupFileSystem_RetrievingFiles_Format, forkBeingRetrieved, numForks)); } var bytesRemaining = (int)fork.Size; var offset = 0; succeeded = false; using (var memory = new System.IO.MemoryStream()) { do { const uint Address = 0u; var bytesToRead = System.Math.Min(bytesRemaining, Device.TotalRAMSize); succeeded = ReadForkToRam.Create(Address, fork.GlobalForkNumber, (uint)offset, bytesToRead).Execute <bool>(device.Port, data); byte[] dataRead = null; if (succeeded) { dataRead = (byte[])DownloadDataBlockFromRam.Create(Address, bytesToRead).Execute(device.Port, data, out succeeded); } if (succeeded) { memory.Write(dataRead, offset, bytesToRead); bytesRemaining -= bytesToRead; offset += bytesToRead; } }while (succeeded && (bytesRemaining > 0)); if (data != null) { data.UpdateTaskProgress((double)forkBeingRetrieved / numForks, string.Format(Resources.Strings.DeviceMultistageCommand_BackupFileSystem_SavingFiles_Format, forkBeingRetrieved, numForks)); } memory.Seek(0, System.IO.SeekOrigin.Begin); using (var tempFile = FileSystemFile.Inflate(memory)) { var fileName = (forkFilenames == null) ? configuration.GetForkDataFileName(fork.GlobalForkNumber) : forkFilenames[forkBeingRetrieved - 1]; var forkPath = System.IO.Path.Combine(destinationDirectory, fileName); forkPath = forkPath.EnsureUniqueFileName(); data.FailureMessage = forkPath; System.IO.Directory.CreateDirectory(System.IO.Path.GetDirectoryName(forkPath)); try { // Test to see if this is a Fork containing a LUIGI file. memory.Seek(0, System.IO.SeekOrigin.Begin); LuigiFileHeader.Inflate(memory); forkPath = System.IO.Path.ChangeExtension(forkPath, ProgramFileKind.LuigiFile.FileExtension()); } catch (INTV.Core.UnexpectedFileTypeException) { // This is OK... we only want to execute certain functions if the file is a LUIGI file. } if (System.IO.File.Exists(forkPath)) { var crcOfTarget = Crc32.OfFile(forkPath); var crcOfSource = Crc32.OfFile(tempFile.FileInfo.FullName); if (crcOfTarget != crcOfSource) { forkPath = forkPath.EnsureUniqueFileName(); System.IO.File.Copy(tempFile.FileInfo.FullName, forkPath); } } else { System.IO.File.Copy(tempFile.FileInfo.FullName, forkPath); } fork.FilePath = forkPath; } } if (!succeeded) { break; } } return(succeeded); }
private static string GetPathForFork(ExecuteDeviceCommandAsyncTaskData data, Fork fork, FileSystem deviceFileSystem, IEnumerable <ProgramDescription> roms, RomListConfiguration romsConfiguration, ref string destinationDir, out bool retrievalNecessary) { retrievalNecessary = false; string forkPath = null; var forkFileKind = ProgramFileKind.None; var crc = 0u; var cfgCrc = 0u; var errors = data.Result as FileSystemSyncErrors; // Determine what kind of fork this is. ILfsFileInfo fileContainingFork = null; var forkKind = deviceFileSystem.GetForkKind(fork, out fileContainingFork); switch (forkKind) { case ForkKind.Program: // Try to fetch LUIGI header from the fork. forkFileKind = ProgramFileKind.LuigiFile; forkPath = GetRomPathForForkFromRomList(data, fork, roms, romsConfiguration.RomsDirectory, out crc, out cfgCrc); if (forkPath == null) { forkPath = GetRomPathForForkFromCache(fork, romsConfiguration.RomsDirectory); } if ((forkPath == null) && string.IsNullOrEmpty(destinationDir)) { destinationDir = romsConfiguration.RomsDirectory; } break; case ForkKind.JlpFlash: if (string.IsNullOrEmpty(destinationDir)) { destinationDir = romsConfiguration.RomsDirectory; // seems sensible to keep save data file(s) next to the ROM } forkFileKind = ProgramFileKind.SaveData; break; case ForkKind.Manual: if (string.IsNullOrEmpty(destinationDir)) { destinationDir = romsConfiguration.ManualsDirectory; } forkFileKind = ProgramFileKind.ManualText; break; case ForkKind.Vignette: if (string.IsNullOrEmpty(destinationDir)) { destinationDir = Configuration.Instance.VignetteDataAreaPath; // keep next to ROM? } forkFileKind = ProgramFileKind.Vignette; break; case ForkKind.Reserved4: case ForkKind.Reserved5: case ForkKind.Reserved6: if (string.IsNullOrEmpty(destinationDir)) { destinationDir = Configuration.Instance.ReservedDataAreaPath; // keep next to ROM? } forkFileKind = ProgramFileKind.GenericSupportFile; errors.UnsupportedForks.Add(new Tuple <ILfsFileInfo, Fork>(fileContainingFork, fork)); ////throw new UnsupportedForkKindException(forkKind); break; case ForkKind.None: // An orphaned fork. Retrieve it, but we can't really do much with it. if (string.IsNullOrEmpty(destinationDir)) { destinationDir = Configuration.Instance.RecoveredDataAreaPath; // orphaned fork } forkFileKind = ProgramFileKind.None; errors.OrphanedForks.Add(fork); break; default: throw new UnsupportedForkKindException(forkKind); } if ((destinationDir != null) && (forkPath == null)) { retrievalNecessary = true; var forkFileBaseName = (fileContainingFork == null) ? Configuration.Instance.GetForkDataFileName(fork.GlobalForkNumber) : fileContainingFork.LongName.EnsureValidFileName(); var extension = forkFileKind.FileExtension(); // For the menu position fork, use the default extension; since it's in the manual fork slot, we want // to override the .txt extension. if (string.IsNullOrEmpty(extension) || (fork.Uid == Fork.MenuPositionForkUid)) { extension = Configuration.ForkExtension; } var forkFileName = System.IO.Path.ChangeExtension(forkFileBaseName, extension); var destFile = System.IO.Path.Combine(destinationDir, forkFileName); if (System.IO.File.Exists(destFile)) { var existingCrc = 0u; var existingCfgCrc = 0u; var luigiHeader = LuigiFileHeader.GetHeader(destFile); if ((luigiHeader != null) && (luigiHeader.Version > 0)) { existingCrc = luigiHeader.OriginalRomCrc32; existingCfgCrc = luigiHeader.OriginalCfgCrc32; } if (existingCrc == 0) { existingCrc = Crc32.OfFile(destFile); } if (existingCfgCrc == 0) { var destCfgFile = System.IO.Path.ChangeExtension(destFile, ProgramFileKind.CfgFile.FileExtension()); if (System.IO.File.Exists(destCfgFile)) { existingCfgCrc = Crc32.OfFile(destCfgFile); } } // This is the equivalent of RomComparerStrict: We skip retrieval only if both the ROM CRCs match and, if available, the .cfg CRCs match. if ((crc != 0) && (existingCrc == crc) && ((cfgCrc == 0) || (existingCfgCrc == cfgCrc))) { retrievalNecessary = false; forkPath = destFile; } else { forkPath = destFile.EnsureUniqueFileName(); } } else { forkPath = destFile; } } if (!string.IsNullOrEmpty(forkPath) && !System.IO.File.Exists(forkPath)) { retrievalNecessary = true; destinationDir = System.IO.Path.GetDirectoryName(forkPath); } return(forkPath); }
/// <summary> /// If the operation should update the file system's dirty flags, and hasn't done so already, do so. /// </summary> /// <param name="currentDirtyFlags">The current dirty flags on the file system.</param> /// <param name="fileSystem">The file system being updated.</param> /// <param name="taskData">Task data for displaying updates, tracking success, etc.</param> /// <param name="globalFileSystemNumber">If an error occurs, the entity type and its global file system number value are used to report the error.</param> /// <param name="operation">The kind of file system operation being done.</param> /// <param name="targetType">The kind of file system entity involved in the operation.</param> /// <returns>The new dirty flags.</returns> private static LfsDirtyFlags UpdateFileSystemDirtyState(this LfsDirtyFlags currentDirtyFlags, FileSystem fileSystem, ExecuteDeviceCommandAsyncTaskData taskData, uint globalFileSystemNumber, LfsOperations operation, LfsEntityType targetType) { if (taskData.Succeeded && !currentDirtyFlags.HasFlag(LfsDirtyFlags.FileSystemUpdateInProgress)) { currentDirtyFlags |= LfsDirtyFlags.FileSystemUpdateInProgress; taskData.Succeeded = SetDirtyFlags.Create(currentDirtyFlags).Execute <bool>(taskData.Device.Port, taskData); } if (!taskData.Succeeded && currentDirtyFlags.HasFlag(LfsDirtyFlags.FileSystemUpdateInProgress)) { var errorFormatString = Resources.Strings.FileSystem_InconsistencyError_Format; if (operation == LfsOperations.Remove) { errorFormatString = Resources.Strings.FileSystem_InconsistencyError_Deleting_Format; } else if (operation == LfsOperations.Add) { errorFormatString = Resources.Strings.FileSystem_InconsistencyError_Creating_Format; } else if (operation == LfsOperations.Update) { errorFormatString = Resources.Strings.FileSystem_InconsistencyError_Updating_Format; } throw new InconsistentFileSystemException(targetType, globalFileSystemNumber, errorFormatString); } fileSystem.Status = currentDirtyFlags; return(currentDirtyFlags); }
/// <summary> /// Initializes a new instance of DeleteOperationData. /// </summary> /// <param name="taskData">Task data for error reporting.</param> /// <param name="targetType">The entry type being deleted.</param> public DeleteOperationData(ExecuteDeviceCommandAsyncTaskData taskData, LfsEntityType targetType) : base(LfsOperations.Remove, taskData) { TargetType = targetType; }
public UploadDataOperationData(ExecuteDeviceCommandAsyncTaskData taskData, uint address) : base(LfsOperations.None, taskData) { Address = address; }