diff --git a/RomRepoMgr.Core/Resources/Localization.Designer.cs b/RomRepoMgr.Core/Resources/Localization.Designer.cs index 6151892..7dc0184 100644 --- a/RomRepoMgr.Core/Resources/Localization.Designer.cs +++ b/RomRepoMgr.Core/Resources/Localization.Designer.cs @@ -356,5 +356,17 @@ namespace RomRepoMgr.Core.Resources { return ResourceManager.GetString("NoChecksumsFound", resourceCulture); } } + + internal static string Copying { + get { + return ResourceManager.GetString("Copying", resourceCulture); + } + } + + internal static string CopyingFile { + get { + return ResourceManager.GetString("CopyingFile", resourceCulture); + } + } } } diff --git a/RomRepoMgr.Core/Resources/Localization.es.resx b/RomRepoMgr.Core/Resources/Localization.es.resx index 8e0b71e..5a3b493 100644 --- a/RomRepoMgr.Core/Resources/Localization.es.resx +++ b/RomRepoMgr.Core/Resources/Localization.es.resx @@ -167,4 +167,10 @@ No es un CHD. + + Copiando {0}... + + + Copiando archivo... + \ No newline at end of file diff --git a/RomRepoMgr.Core/Resources/Localization.resx b/RomRepoMgr.Core/Resources/Localization.resx index 3b08db0..19dde30 100644 --- a/RomRepoMgr.Core/Resources/Localization.resx +++ b/RomRepoMgr.Core/Resources/Localization.resx @@ -172,4 +172,10 @@ No checksums found. + + Copying {0}... + + + Copying file... + \ No newline at end of file diff --git a/RomRepoMgr.Core/Workers/FileExporter.cs b/RomRepoMgr.Core/Workers/FileExporter.cs index 68e8bcc..f0ac612 100644 --- a/RomRepoMgr.Core/Workers/FileExporter.cs +++ b/RomRepoMgr.Core/Workers/FileExporter.cs @@ -17,6 +17,7 @@ namespace RomRepoMgr.Core.Workers { public class FileExporter { + const long BUFFER_SIZE = 131072; readonly string _outPath; readonly long _romSetId; long _filePosition; @@ -106,6 +107,172 @@ namespace RomRepoMgr.Core.Workers Message = machine.Name }); + Dictionary disksByMachine = Context.Singleton.DisksByMachines. + Where(f => f.Machine.Id == machine.Id && + f.Disk.IsInRepo). + ToDictionary(f => f.Name); + + string machineName = machine.Name; + + if(disksByMachine.Count > 0) + { + SetProgress2Bounds?.Invoke(this, new ProgressBoundsEventArgs + { + Minimum = 0, + Maximum = disksByMachine.Count + }); + + if(machineName.EndsWith(".zip", StringComparison.InvariantCultureIgnoreCase)) + machineName = machineName.Substring(0, machineName.Length - 4); + + string machinePath = Path.Combine(_outPath, machineName); + + if(!Directory.Exists(machinePath)) + Directory.CreateDirectory(machinePath); + + long diskPosition = 0; + + foreach(KeyValuePair diskByMachine in disksByMachine) + { + string outputPath = Path.Combine(machinePath, diskByMachine.Key); + + if(!outputPath.EndsWith(".chd", StringComparison.InvariantCultureIgnoreCase)) + outputPath += ".chd"; + + SetProgress2?.Invoke(this, new ProgressEventArgs + { + Value = diskPosition + }); + + string repoPath = null; + string md5Path = null; + string sha1Path = null; + + DbDisk disk = diskByMachine.Value.Disk; + + if(disk.Sha1 != null) + { + byte[] sha1Bytes = new byte[20]; + string sha1 = disk.Sha1; + + for(int i = 0; i < 20; i++) + { + if(sha1[i * 2] >= 0x30 && + sha1[i * 2] <= 0x39) + sha1Bytes[i] = (byte)((sha1[i * 2] - 0x30) * 0x10); + else if(sha1[i * 2] >= 0x41 && + sha1[i * 2] <= 0x46) + sha1Bytes[i] = (byte)((sha1[i * 2] - 0x37) * 0x10); + else if(sha1[i * 2] >= 0x61 && + sha1[i * 2] <= 0x66) + sha1Bytes[i] = (byte)((sha1[i * 2] - 0x57) * 0x10); + + if(sha1[(i * 2) + 1] >= 0x30 && + sha1[(i * 2) + 1] <= 0x39) + sha1Bytes[i] += (byte)(sha1[(i * 2) + 1] - 0x30); + else if(sha1[(i * 2) + 1] >= 0x41 && + sha1[(i * 2) + 1] <= 0x46) + sha1Bytes[i] += (byte)(sha1[(i * 2) + 1] - 0x37); + else if(sha1[(i * 2) + 1] >= 0x61 && + sha1[(i * 2) + 1] <= 0x66) + sha1Bytes[i] += (byte)(sha1[(i * 2) + 1] - 0x57); + } + + string sha1B32 = Base32.ToBase32String(sha1Bytes); + + sha1Path = Path.Combine(Settings.Settings.Current.RepositoryPath, "chd", "sha1", + sha1B32[0].ToString(), sha1B32[1].ToString(), sha1B32[2].ToString(), + sha1B32[3].ToString(), sha1B32[4].ToString(), sha1B32 + ".chd"); + } + + if(disk.Md5 != null) + { + byte[] md5Bytes = new byte[16]; + string md5 = disk.Md5; + + for(int i = 0; i < 16; i++) + { + if(md5[i * 2] >= 0x30 && + md5[i * 2] <= 0x39) + md5Bytes[i] = (byte)((md5[i * 2] - 0x30) * 0x10); + else if(md5[i * 2] >= 0x41 && + md5[i * 2] <= 0x46) + md5Bytes[i] = (byte)((md5[i * 2] - 0x37) * 0x10); + else if(md5[i * 2] >= 0x61 && + md5[i * 2] <= 0x66) + md5Bytes[i] = (byte)((md5[i * 2] - 0x57) * 0x10); + + if(md5[(i * 2) + 1] >= 0x30 && + md5[(i * 2) + 1] <= 0x39) + md5Bytes[i] += (byte)(md5[(i * 2) + 1] - 0x30); + else if(md5[(i * 2) + 1] >= 0x41 && + md5[(i * 2) + 1] <= 0x46) + md5Bytes[i] += (byte)(md5[(i * 2) + 1] - 0x37); + else if(md5[(i * 2) + 1] >= 0x61 && + md5[(i * 2) + 1] <= 0x66) + md5Bytes[i] += (byte)(md5[(i * 2) + 1] - 0x57); + } + + string md5B32 = Base32.ToBase32String(md5Bytes); + + md5Path = Path.Combine(Settings.Settings.Current.RepositoryPath, "chd", "md5", + md5B32[0].ToString(), md5B32[1].ToString(), md5B32[2].ToString(), + md5B32[3].ToString(), md5B32[4].ToString(), md5B32 + ".chd"); + } + + if(File.Exists(sha1Path)) + repoPath = sha1Path; + else if(File.Exists(md5Path)) + repoPath = md5Path; + + if(repoPath == null) + throw new ArgumentException(string.Format(Localization.CannotFindHashInRepository, + disk.Sha1 ?? disk.Md5)); + + var inFs = new FileStream(repoPath, FileMode.Open, FileAccess.Read); + var outFs = new FileStream(outputPath, FileMode.Create, FileAccess.Write); + + SetMessage3?.Invoke(this, new MessageEventArgs + { + Message = string.Format(Localization.Copying, Path.GetFileName(outputPath)) + }); + + SetProgress3Bounds?.Invoke(this, new ProgressBoundsEventArgs + { + Minimum = 0, + Maximum = inFs.Length + }); + + byte[] buffer = new byte[BUFFER_SIZE]; + + while(inFs.Position + BUFFER_SIZE <= inFs.Length) + { + SetProgress3?.Invoke(this, new ProgressEventArgs + { + Value = inFs.Position + }); + + inFs.Read(buffer, 0, buffer.Length); + outFs.Write(buffer, 0, buffer.Length); + } + + buffer = new byte[inFs.Length - inFs.Position]; + + SetProgress3?.Invoke(this, new ProgressEventArgs + { + Value = inFs.Position + }); + + inFs.Read(buffer, 0, buffer.Length); + outFs.Write(buffer, 0, buffer.Length); + + inFs.Close(); + outFs.Close(); + + diskPosition++; + } + } + _filesByMachine = Context.Singleton.FilesByMachines. Where(f => f.Machine.Id == machine.Id && f.File.IsInRepo). ToDictionary(f => f.Name); @@ -124,8 +291,6 @@ namespace RomRepoMgr.Core.Workers Maximum = _filesByMachine.Count }); - string machineName = machine.Name; - if(!machineName.EndsWith(".zip", StringComparison.InvariantCultureIgnoreCase)) machineName += ".zip"; diff --git a/RomRepoMgr.Core/Workers/FileImporter.cs b/RomRepoMgr.Core/Workers/FileImporter.cs index b51f185..1d31c79 100644 --- a/RomRepoMgr.Core/Workers/FileImporter.cs +++ b/RomRepoMgr.Core/Workers/FileImporter.cs @@ -563,8 +563,8 @@ namespace RomRepoMgr.Core.Workers int nibble1 = chd.SHA1[i] >> 4; int nibble2 = chd.SHA1[i] & 0xF; - nibble1 += nibble1 >= 0xA ? 0x37 : 0x30; - nibble2 += nibble2 >= 0xA ? 0x37 : 0x30; + nibble1 += nibble1 >= 0xA ? 0x57 : 0x30; + nibble2 += nibble2 >= 0xA ? 0x57 : 0x30; chdArray[i * 2] = (char)nibble1; chdArray[(i * 2) + 1] = (char)nibble2; @@ -642,12 +642,16 @@ namespace RomRepoMgr.Core.Workers dbDisk.UpdatedOn = DateTime.UtcNow; } - if(dbDisk.Size == null || - dbDisk.Size > uSize) + if(dbDisk.Size > uSize) { - dbDisk.Size = uSize; - dbDisk.UpdatedOn = DateTime.UtcNow; knownDiskWasBigger = true; + dbDisk.Size = null; + } + + if(dbDisk.Size == null) + { + dbDisk.Size = uSize; + dbDisk.UpdatedOn = DateTime.UtcNow; } string md5Path = null; @@ -720,7 +724,7 @@ namespace RomRepoMgr.Core.Workers SetMessage2?.Invoke(this, new MessageEventArgs { - Message = Localization.CompressingFile + Message = Localization.CopyingFile }); byte[] buffer = new byte[BUFFER_SIZE]; @@ -765,7 +769,7 @@ namespace RomRepoMgr.Core.Workers if(_deleteAfterImport) File.Delete(path); - if(!knownDiskWasBigger) + if(knownDiskWasBigger) File.Delete(repoPath + ".bak"); return true;