/************************************************************* *************************************************************/ public bool AnalyseISOBuilder(IsoBuilder bld) { ParamSfo sfo = ParamSfo.Load(Path.Combine(bld.Path, @"PS3_GAME\PARAM.SFO")); GameID = sfo.GetStringValue("TITLE_ID"); NumPlainRegions = (uint)((bld.Regions.Count + 1) / 2); Regions = bld.Regions.ToArray(); amountOfSectors = Regions.Last().Length; return(true); }
public static ParamSfo Load(Stream s) { // Read magic using (BinaryReader br = new BinaryReader(s)) { ParamSfo sfo = new ParamSfo(); sfo.Magic = Encoding.ASCII.GetString(br.ReadBytes(4)).Trim('\0'); if (sfo.Magic != "PSF") { throw new FileLoadException("Invalid SFO file"); } sfo.Version = br.ReadUInt32(); // Version uint keyTableOffset = br.ReadUInt32(); uint dataTableOffset = br.ReadUInt32(); uint indexTableEntries = br.ReadUInt32(); sfo.IndexTables = new IndexTable[indexTableEntries]; for (int i = 0; i < indexTableEntries; i++) { sfo.IndexTables[i] = new IndexTable(br); } for (int i = 0; i < indexTableEntries; i++) { s.Position = keyTableOffset + sfo.IndexTables[i].KeyTableOffset; uint size = ((i == indexTableEntries - 1) ? dataTableOffset - keyTableOffset : sfo.IndexTables[i + 1].KeyTableOffset) - sfo.IndexTables[i].KeyTableOffset; sfo.IndexTables[i].Name = Encoding.ASCII.GetString(br.ReadBytes((int)size)).Trim('\0'); s.Position = dataTableOffset + sfo.IndexTables[i].DataTableOffset; switch (sfo.IndexTables[i].ParamFormat) { case 0x404: // Read integer sfo.IndexTables[i].IntValue = br.ReadInt32(); break; default: sfo.IndexTables[i].StringValue = Encoding.UTF8.GetString(br.ReadBytes((int)sfo.IndexTables[i].ParamLength)).Trim('\0'); break; } } return(sfo); } }
protected async Task InternalCreateIRD(string savePath, CancellationToken cancellation, string isoPath = null) { byte[] buffer = new byte[Utilities.SectorSize]; List <FileHash> fileList = new List <FileHash>(); try { // First, get the partition table of this iso using (Stream fs = Open()) { if (fs == null) { return; } PS3CDReader reader = new PS3CDReader(fs); List <DirectoryMemberInformation> files = reader.Members.Where(d => d.IsFile).Distinct().ToList(); StartOfDataSector = files.First().StartSector; EndOfDataSector = files.Last().StartSector + files.Last().TotalSectors; var updateFile = files.FirstOrDefault( d => d.Path.Equals("/PS3_UPDATE/PS3UPDAT.PUP", StringComparison.OrdinalIgnoreCase)); long updateOffset = updateFile != null ? updateFile.StartSector * Utilities.SectorSize : 0; fileList.AddRange(files.Select(d => new FileHash(d.StartSector, d.Length))); if (cancellation.IsCancellationRequested) { return; } IrdFile irdFile = IrdFile.New(); using (Stream s = reader.OpenFile("PS3_GAME\\PARAM.SFO", FileMode.Open, FileAccess.Read)) { ParamSfo sfo = ParamSfo.Load(s); irdFile.AppVersion = sfo.GetStringValue("APP_VER"); irdFile.GameVersion = sfo.GetStringValue("VERSION"); irdFile.GameID = sfo.GetStringValue("TITLE_ID"); irdFile.GameName = sfo.GetStringValue("TITLE"); } Interaction.Instance.ReportMessage("Processing " + (string.IsNullOrEmpty(irdFile.GameName) ? irdFile.GameID : irdFile.GameName)); irdFile.UpdateVersion = Utilities.FindUpdateVersion(fs, updateOffset); using (FileStream isoStream = string.IsNullOrEmpty(isoPath) ? null : new FileStream(isoPath, FileMode.Create, FileAccess.Write)) { if (isoStream != null) { isoStream.SetLength(TotalSectors * Utilities.SectorSize); } using (IOStream ioStream = new IOStream(fs, isoStream)) { ioStream.Seek(0, SeekOrigin.Begin); // Read the header, until StartOfDataSector (in sectors) irdFile.Header = new MemoryStream(); for (int i = 0; i < StartOfDataSector; i++) { int bytesRead = ioStream.Read(buffer, 0, buffer.Length); irdFile.Header.Write(buffer, 0, bytesRead); Interaction.Instance.ReportProgress(i); if (cancellation.IsCancellationRequested) { return; } } irdFile.ExtractAuthData(); // Fix the regions for the actual interesting data Regions.First().Start = (uint)StartOfDataSector; Regions.First().Length -= (uint)StartOfDataSector; Regions.Last().Length = (uint)EndOfDataSector - Regions.Last().Start; // Now, we should calculate the md5 sums of all regions Interaction.Instance.ReportMessage("Calculating hashes for " + Regions.Length + " regions."); for (int i = 0; i < Regions.Length; i++) { // Calculate the hash Interaction.Instance.ReportMessage( "Calculate hash for region " + i + " (" + Regions[i].Start.ToString("X2") + "-" + Regions[i].End.ToString("X2") + ")"); ioStream.Seek(Regions[i].Start * Utilities.SectorSize, SeekOrigin.Begin); using (FileHashStream fhs = new FileHashStream(fileList, Regions[i].Start)) { await Regions[i].CopyRegion(cancellation, ioStream, fhs); if (cancellation.IsCancellationRequested) { return; } irdFile.RegionHashes.Add(Regions[i].SourceHash); Interaction.Instance.ReportMessage("Region " + i + " hash: " + Regions[i].SourceHash.AsString()); } } ioStream.Seek(EndOfDataSector * Utilities.SectorSize, SeekOrigin.Begin); irdFile.Footer = new MemoryStream(); for (long i = EndOfDataSector; i < TotalSectors; i++) { int bytesRead = ioStream.Read(buffer, 0, buffer.Length); irdFile.Footer.Write(buffer, 0, bytesRead); Interaction.Instance.ReportProgress((int)(ioStream.Position / Utilities.SectorSize)); if (cancellation.IsCancellationRequested) { return; } } } } irdFile.FileHashes = fileList.ToDictionary(t => t.StartSector, t => t.Hash); irdFile.Save(savePath); Interaction.Instance.ReportMessage("All done, IRD file saved to " + savePath); } } catch (BadReadException e) { Interaction.Instance.ReportMessage(e.Message, ReportType.Fail); } catch (AuthenticationException e) { Interaction.Instance.ReportMessage(e.Message, ReportType.Fail); } }