public static void WriteIso(UmdDisc disc, string filename) { using var stream = new FileStream(filename, FileMode.Open, FileAccess.Write); using var writer = new BinaryWriter(stream); foreach (var sector in disc.Sectors) { } }
public static byte[] DecodeData(UmdDiscSector sector, UmdDisc disc, UmdDisc parentDisc) { return(sector.Encoding switch { UmdEncoding.None => sector.Data ?? throw new InvalidOperationException("No data in sector"), UmdEncoding.InternalLink => DecodeInternalLink(sector, disc) ?? throw new InvalidOperationException("Internally linked sector has no data."), UmdEncoding.ExternalLink => DecodeExternalLink(sector, parentDisc) ?? throw new InvalidOperationException("Internally linked sector has no data."), _ => throw new InvalidOperationException("Unsupported encoding") });
// TODO: optimize this method public static async Task Merge(UmdDisc masterDisc, UmdDisc disc) { var masterSectors = masterDisc.Sectors.Where(s => s.Encoding == UmdEncoding.None).OrderBy(s => s.Crc32).ToList(); var sectors = disc.Sectors.Where(s => s.Encoding == UmdEncoding.None).OrderBy(s => s.Crc32).ToList(); // if nothing to compare return if ((masterSectors == null) || (sectors == null) || (!masterSectors.Any()) || (!sectors.Any())) { return; } int masterCursor = 0, cursor = 0; // sync cursors while ((masterCursor < masterSectors.Count) && (cursor < sectors.Count)) { if (masterSectors[masterCursor].Crc32 == sectors[cursor].Crc32) { int subCursor = 0; while ((masterCursor + subCursor < masterSectors.Count) && (masterSectors[masterCursor].Crc32 == masterSectors[masterCursor + subCursor].Crc32)) { if ((masterSectors[masterCursor + subCursor].Data != null) && (sectors[cursor].Data != null) && (await BinaryComparer.Compare(masterSectors[masterCursor + subCursor].Data, 0, sectors[cursor].Data, 0, UmdDisc.SectorSize))) { sectors[cursor].Encoding = UmdEncoding.ExternalLink; sectors[cursor].Data = GetLinkData(masterSectors[masterCursor + subCursor].Id); sectors[cursor].Length = 4; sectors[cursor].Crc32 = Crc32Algorithm.Compute(sectors[cursor].Data, 0, 4); break; } subCursor++; } cursor++; continue; } if (masterSectors[masterCursor].Crc32 < sectors[cursor].Crc32) { masterCursor++; continue; } if (masterSectors[masterCursor].Crc32 > sectors[cursor].Crc32) { cursor++; continue; } } }
public static async Task InternalMerge(UmdDisc disc) { IEnumerable <UmdDiscSector> sectors = disc.Sectors.Where(s => s.Encoding == UmdEncoding.None).ToList(); uint pass = 1; while (sectors.Any()) { System.Console.WriteLine($"Internal merge pass {pass}: {sectors.Count()} sectors."); sectors = await InternalMergePass(sectors); pass++; } }
public static UmdDisc?ReadFromIso(string filename, bool withData = false) { const ushort sectorSize = 2048; try { var result = new UmdDisc(); var fileInfo = new FileInfo(filename); if (fileInfo.Length % sectorSize != 0) { return(null); } var buffer = new byte[sectorSize]; using var stream = new FileStream(filename, FileMode.Open, FileAccess.Read); using var reader = new BinaryReader(stream); uint sectorCount = (uint)(fileInfo.Length / sectorSize); for (uint i = 0; i < sectorCount; i++) { reader.Read(buffer, 0, sectorSize); var sector = new UmdDiscSector { Id = i, Crc32 = Crc32Algorithm.Compute(buffer, 0, sectorSize), Length = sectorSize, StartPostiion = (uint)(i * sectorSize) }; if (withData) { sector.Data = buffer; buffer = new byte[sectorSize]; } result.Sectors.Add(sector); } return(result); } catch { return(null); } }
private static byte[]? DecodeInternalLink(UmdDiscSector sector, UmdDisc disc) { var sectorId = BitConverter.ToInt32(sector.Data); return(disc.Sectors[sectorId].Data); }