protected virtual void Dispose(bool disposing) { if (!disposedValue) { if (ISOStream != null && ISOStream.CanSeek) { ISOStream.Dispose(); } disposedValue = true; } }
public ISO ExtractISO() { // read game and region ISOStream.Seek(0, SeekOrigin.Begin); int game = ISOStream.GetUShortAtOffset(1); var region = ISOStream.ReadByte(); Game gameEnum; Region regionEnum; switch (game) { case (ushort)Game.Colosseum: case (ushort)Game.XD: gameEnum = (Game)game; break; default: throw new Exception("Unsupported game!"); } switch (region) { case (byte)Region.US: case (byte)Region.Europe: case (byte)Region.Japan: regionEnum = (Region)region; break; default: throw new Exception("Unknown region!"); } ExtractPath = $"{Configuration.ExtractDirectory}/{gameEnum}-{regionEnum}"; if (!Directory.Exists(ExtractPath) && !Configuration.UseMemoryStreams) { Directory.CreateDirectory(ExtractPath); } var iso = new ISO(ISOStream, ExtractPath) { Game = gameEnum, Region = regionEnum, DOL = new DOL(ExtractPath, this), TOC = new FST(ExtractPath, this) }; oldOffsets = iso.TOC.GetFlattenedFST().ToDictionary(k => k.Name.ToString(), v => v is FSTFileEntry fe ? fe.FileDataOffset : 0); iso.CommonRel = iso.GetFSysFile("common.fsys").GetEntryByFileName("common_rel.rel") as REL; iso.BuildStringTables(); return(iso); }
public void RepackISO(ISO iso, string savePath) { if (!savePath.EndsWith(".iso")) { savePath = $"{savePath}.iso"; } using var isoStream = File.Open(savePath, FileMode.Create, FileAccess.Write); // boot.bin, bi2.bin, appldr.bin ISOStream.Seek(0, SeekOrigin.Begin); ISOStream.CopySubStream(isoStream, 0, iso.DOL.Offset); // pack dol isoStream.Seek(iso.DOL.Offset, SeekOrigin.Begin); using var dolStream = iso.DOL.Encode(); dolStream.CopyTo(isoStream); int alignment = AlignByteCount(iso.DOL.Offset + (int)iso.DOL.ExtractedFile.Length); isoStream.WriteBytesAtOffset(isoStream.Position, new byte[alignment]); if (iso.TOC.StartDataOffset == uint.MaxValue) { throw new Exception("This is awkward... For some reason the TOC was never loaded."); } // pack fsys files isoStream.Seek(iso.TOC.StartDataOffset, SeekOrigin.Begin); iso.TOC.ReorderFST(); var fileEntries = iso.TOC.GetFlattenedFST().OrderBy(f => f is FSTFileEntry fe ? fe.FileDataOffset : 0).ToArray(); for (int i = 0; i < fileEntries.Length; i++) { var newEntry = fileEntries[i]; if (newEntry is FSTFileEntry fileEntry) { var fsysStartOffset = fileEntry.FileDataOffset; var fsysSize = fileEntry.Size; var entryFileName = fileEntry.Name.ToString(); isoStream.Seek(fileEntry.FileDataOffset, SeekOrigin.Begin); if (iso.Files.ContainsKey(entryFileName)) { var fsys = iso.Files[entryFileName]; using var fsysStream = fsys.Encode(); fsysStream.CopyTo(isoStream); if (fsysStream.Length != fileEntry.Size) { var adjustSize = fsysStream.Length - fileEntry.Size; if (adjustSize < 0) { continue; } fileEntry.Size = (uint)fsysStream.Length; for (int j = i + 1; j < fileEntries.Length; j++) { if (fileEntries[j] is FSTFileEntry fe) { fe.FileDataOffset += (uint)adjustSize; } } } } else { ISOStream.CopySubStream(isoStream, oldOffsets[entryFileName], fsysSize); } isoStream.Flush(); } } if (isoStream.Position < ISOStream.Length) { isoStream.Write(new byte[ISOStream.Length - isoStream.Position]); } // pack FST after to account for updates iso.TOC.RebuildFST(); isoStream.Seek(iso.TOC.Offset, SeekOrigin.Begin); using var tocstream = iso.TOC.Encode(); tocstream.CopyTo(isoStream); if (isoStream.Position < iso.TOC.StartDataOffset) { isoStream.Write(new byte[iso.TOC.StartDataOffset - isoStream.Position]); } isoStream.Flush(); }