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); }
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); }