private Directory BuildContentTree(Stream stream, GENESTRT nameTable, PACKTOC toc, PACKTOC.DirectoryEntry dirEnt) { Directory dir = new Directory(nameTable.Strings[(int)dirEnt.NameIndex]); for (uint i = dirEnt.FirstEntryIndex; i < dirEnt.FirstEntryIndex + dirEnt.NumEntries; i++) { PACKTOC.Entry entry = toc.Entries[(int)i]; string name = nameTable.Strings[(int)entry.NameIndex]; if (entry is PACKTOC.UncompressedFileEntry uFileEntry) { byte[] rawData = new byte[uFileEntry.Size]; stream.Seek((long)uFileEntry.Offset, SeekOrigin.Begin); stream.Read(rawData); dir.Children.Add(new File(name, rawData, false, uFileEntry.Size)); } else if (entry is PACKTOC.DirectoryEntry directoryEntry) { dir.Children.Add(this.BuildContentTree(stream, nameTable, toc, directoryEntry)); } else if (entry is PACKTOC.CompressedFileEntry cFileEntry) { byte[] rawData = new byte[cFileEntry.CompressedSize]; stream.Seek((long)cFileEntry.Offset, SeekOrigin.Begin); stream.Read(rawData); dir.Children.Add(new File(name, rawData, true, cFileEntry.UncompressedSize)); } } return(dir); }
private static Metric ConvertToParsedMetric(GOPGMET.Metric metric, GENESTRT strt) { if (metric is GOPGMET.StringMetric str) { StringMetric parsed = new StringMetric(); parsed.Name = strt.Strings[str.NameIndex]; foreach (ushort index in str.ValueIndices) { parsed.Values.Add(strt.Strings[index]); } return(parsed); } else if (metric is GOPGMET.ReferenceMetric reference) { ReferenceMetric parsed = new ReferenceMetric(); parsed.Name = strt.Strings[reference.NameIndex]; foreach (GOPGMET.Metric referenced in reference.ReferencedMetrics) { parsed.ReferencedMetrics.Add(ConvertToParsedMetric(referenced, strt)); } return(parsed); } else { throw new Exception("Unknown raw metric type \"" + metric.GetType() + "\"."); } }
private static GOPGMET.Metric ConvertToRawMetric(Metric metric, GENESTRT strt) { if (metric is StringMetric str) { GOPGMET.StringMetric raw = new GOPGMET.StringMetric(); raw.NameIndex = (ushort)strt.AddString(str.Name); foreach (string value in str.Values) { raw.ValueIndices.Add((ushort)strt.AddString(value)); } return(raw); } else if (metric is ReferenceMetric reference) { GOPGMET.ReferenceMetric raw = new GOPGMET.ReferenceMetric(); raw.NameIndex = (ushort)strt.AddString(reference.Name); foreach (Metric referenced in reference.ReferencedMetrics) { raw.ReferencedMetrics.Add(ConvertToRawMetric(referenced, strt)); } return(raw); } else { throw new Exception("Unknown parsed metric type \"" + metric.GetType() + "\"."); } }
private FileSet ReadFileSet(Stream stream, string name) { FileSet fileSet = new FileSet(name); using (BinaryReader reader = new BinaryReader(stream)) { SectionSet fileSetSections = SectionIO.ReadAll(reader); PACKFSHD fileSetHeader = fileSetSections.Get <PACKFSHD>(); GENESTRT fileSetNameTable = fileSetSections.Get <GENESTRT>(); foreach (PACKFSHD.FileEntry fEntry in fileSetHeader.Files) { string fName = fileSetNameTable.Strings[(int)fEntry.NameIndex]; byte[] rawData = new byte[fEntry.CompressedSize]; stream.Seek((long)fEntry.Offset, SeekOrigin.Begin); stream.Read(rawData); if (fEntry.Unknown != 0x2) { throw new Exception("Unsupported value of unknown file set file entry field: " + fEntry.Unknown); } fileSet.Files.Add(new File(fName, rawData, true, fEntry.UncompressedSize)); } } return(fileSet); }
public APK(Stream stream) { using (BinaryReader reader = new BinaryReader(stream)) { SectionSet sections = SectionIO.ReadAll(reader); // TODO: Figure out what hash is calculated from and validate hash. PACKHEDR hedr = sections.Get <PACKHEDR>(); GENESTRT nameTable = sections.Get <GENESTRT>(); this.Name = nameTable.Strings[(int)hedr.NameIndex]; PACKTOC toc = sections.Get <PACKTOC>(); this.RootDirectory = this.BuildContentTree(stream, nameTable, toc, (PACKTOC.DirectoryEntry)toc.Entries[0]); PACKFSLS fileSetList = sections.Get <PACKFSLS>(); foreach (PACKFSLS.FileSetEntry entry in fileSetList.FileSets) { stream.Seek((long)entry.Offset, SeekOrigin.Begin); byte[] fileSetData = reader.ReadBytes((int)entry.Size); string fileSetName = nameTable.Strings[(int)entry.NameIndex]; if (!Enumerable.SequenceEqual(new MD5CryptoServiceProvider().ComputeHash(fileSetData), entry.Hash)) { throw new Exception("Hash mismatch in file set \"" + fileSetName + "\"."); } using (MemoryStream fileSetStream = new MemoryStream(fileSetData)) { this.FileSets.Add(this.ReadFileSet(fileSetStream, fileSetName)); } } } }
public IDX(params string[] apkFiles) { this.sections = new SectionSet(); this.sections.Add(new ENDILTLE()); List <SectionSet> apks = new List <SectionSet>(); foreach (string apkFile in apkFiles) { using (FileStream stream = File.OpenRead(apkFile)) { apks.Add(SectionIO.ReadAll(stream)); } } PACKTOC combinedToc = new PACKTOC(); PACKFSLS combinedFsls = new PACKFSLS(); GENESTRT combinedStrt = new GENESTRT(); foreach (SectionSet set in apks) { PACKHEDR hedr = set.Get <PACKHEDR>(); GENESTRT strt = set.Get <GENESTRT>(); hedr.NameIndex = combinedStrt.AddString(strt.Strings[(int)hedr.NameIndex]); this.sections.Add(hedr); } uint packageIndex = 0; foreach (SectionSet set in apks) { PACKTOC toc = set.Get <PACKTOC>(); PACKFSLS fsls = set.Get <PACKFSLS>(); GENESTRT strt = set.Get <GENESTRT>(); foreach (PACKTOC.Entry entry in toc.Entries) { entry.NameIndex = combinedStrt.AddString(strt.Strings[(int)entry.NameIndex]); entry.PackageIndex = packageIndex; combinedToc.Entries.Add(entry); } foreach (PACKFSLS.FileSetEntry entry in fsls.FileSets) { entry.NameIndex = combinedStrt.AddString(strt.Strings[(int)entry.NameIndex]); entry.PackageIndex = packageIndex; combinedFsls.FileSets.Add(entry); } packageIndex++; } this.sections.Add(combinedToc); this.sections.Add(combinedFsls); this.sections.Add(combinedStrt); this.sections.Add(new GENEEOF()); }
private static GENESTRT GetGENESTRT(EndianBinaryReader br, long headerOffset, long headerSize) { GENESTRT genetmp = new GENESTRT(); long tmp = br.BaseStream.Position; long tmp2 = headerOffset + headerSize; br.BaseStream.Position = tmp2; while (br.BaseStream.Position != br.BaseStream.Length) { if (br.ReadByte() == '\0') { } else { br.BaseStream.Position -= 1; char tmpchar = (char)br.ReadByte(); if (tmpchar == 'G') { tmpchar = (char)br.ReadByte(); if (tmpchar == 'E') { br.BaseStream.Position -= 2; if (Encoding.ASCII.GetString(br.ReadBytes(8)) == "GENESTRT") { genetmp.offset = br.BaseStream.Position - 8; break; } } } } } br.ReadInt32(); br.ReadInt32(); long headend = br.BaseStream.Position; genetmp.stringcnt = br.ReadInt32(); br.ReadInt32(); long genehsize = br.ReadInt32(); br.ReadInt32(); genetmp.nameofflist = new long[genetmp.stringcnt]; for (int i = 0; i < genetmp.stringcnt; i++) { genetmp.nameofflist[i] = br.ReadInt32(); } br.BaseStream.Position = headend + genehsize; genetmp.names_off = br.BaseStream.Position; genetmp.stringlist = new string[genetmp.stringcnt]; for (int j = 0; j < genetmp.stringcnt; j++) { genetmp.stringlist[j] = ReadStringZ(br); } br.BaseStream.Position = tmp; return(genetmp); }
private void WriteFileSet(Stream stream, FileSet fileSet) { PACKFSHD fileSetHeader = new PACKFSHD(); GENESTRT fileSetNameTable = new GENESTRT(); fileSetHeader.Unknown = 0x10000; fileSetHeader.DataOffset = 0; // Filled in later. foreach (File file in fileSet.Files) { PACKFSHD.FileEntry fileEntry = new PACKFSHD.FileEntry(); fileEntry.NameIndex = fileSetNameTable.AddString(file.Name); fileEntry.Unknown = 0x2; fileEntry.Offset = 0; // Filled in later. fileEntry.UncompressedSize = file.UncompressedSize; fileEntry.CompressedSize = (uint)file.RawData.Length; fileSetHeader.Files.Add(fileEntry); } SectionSet fileSetSections = new SectionSet(); fileSetSections.Add(new ENDILTLE()); fileSetSections.Add(fileSetHeader); fileSetSections.Add(fileSetNameTable); fileSetSections.Add(new GENEEOF()); ulong headersSize; using (MemoryStream sizeTestStream = new MemoryStream()) { SectionIO.WriteAll(sizeTestStream, fileSetSections); headersSize = (ulong)sizeTestStream.Length; } ulong currOffset = NumberUtil.Align(headersSize, 0x10); fileSetHeader.DataOffset = (uint)currOffset - 0x10; // Offset excludes ENDILTLE. foreach (PACKFSHD.FileEntry fileEntry in fileSetHeader.Files) { fileEntry.Offset = currOffset; currOffset = NumberUtil.Align(currOffset + fileEntry.CompressedSize, 0x10); } SectionIO.WriteAll(stream, fileSetSections); foreach (File file in fileSet.Files) { stream.Write(file.RawData); stream.PadTo(0x10); } }
public GOP(Stream stream) { SectionSet sections = SectionIO.ReadAll(stream); GOPGMET met = sections.Get <GOPGMET>(); GOPGREC rec = sections.Get <GOPGREC>(); GENESTRT strt = sections.Get <GENESTRT>(); GOPGDAT dat = sections.Get <GOPGDAT>(); foreach (GOPGREC.ElementInfo elementInfo in rec.Elements) { Element element = new Element(); element.Name = strt.Strings[elementInfo.NameIndex]; element.Type = elementInfo.Type; element.Unknown = elementInfo.Unknown; this.Elements.Add(element); } this.Records = new string[dat.Records.Count, rec.Elements.Count + 1]; int recordIndex = 0; foreach (GOPGDAT.Record record in dat.Records) { this.Records[recordIndex, 0] = record.Index.ToString(); using (MemoryStream dataStream = new MemoryStream(record.Data)) { using (BinaryReader dataReader = new BinaryReader(dataStream)) { for (int i = 0; i < rec.Elements.Count; i++) { GOPGREC.ElementInfo elementInfo = rec.Elements[i]; dataStream.Seek(elementInfo.Offset, SeekOrigin.Begin); this.Records[recordIndex, i + 1] = ReadElement(dataReader, elementInfo, strt); } } } recordIndex++; } this.RootMetric = ConvertToParsedMetric(met.Root, strt); }
public void Write(Stream stream) { SectionSet sections = new SectionSet(); GOPGFIN fin = new GOPGFIN(); fin.Unknown1 = 0x2; fin.Unknown2 = 0x1; sections.Add(fin); GOPGMET met = new GOPGMET(); GOPGREC rec = new GOPGREC(); GENESTRT strt = new GENESTRT(); GOPGDAT dat = new GOPGDAT(); strt.AddString(""); uint currElementPos = 0; foreach (Element element in this.Elements) { uint padTo = ELEMENT_PAD_TO[element.Type]; currElementPos = (currElementPos + (padTo - 1)) & ~(padTo - 1); GOPGREC.ElementInfo info = new GOPGREC.ElementInfo(); info.Type = element.Type; info.Offset = currElementPos; info.NameIndex = (ushort)strt.AddString(element.Name); info.Unknown = element.Unknown; rec.Elements.Add(info); currElementPos += ELEMENT_LENGTH[element.Type]; } for (int recordIndex = 0; recordIndex < this.Records.GetLength(0); recordIndex++) { using (MemoryStream dataStream = new MemoryStream()) { using (BinaryWriter dataWriter = new BinaryWriter(dataStream)) { for (int elementIndex = 0; elementIndex < this.Elements.Count; elementIndex++) { string element = this.Records[recordIndex, elementIndex + 1]; GOPGREC.ElementInfo elementInfo = rec.Elements[elementIndex]; dataWriter.PadTo((int)ELEMENT_PAD_TO[elementInfo.Type]); WriteElement(dataWriter, elementInfo, strt, element); } dataWriter.PadTo(0x4); } GOPGDAT.Record record = new GOPGDAT.Record(); record.Index = uint.Parse(this.Records[recordIndex, 0]); record.Data = dataStream.ToArray(); dat.Records.Add(record); } } met.Root = ConvertToRawMetric(this.RootMetric, strt); sections.Add(met); sections.Add(rec); sections.Add(strt); sections.Add(dat); sections.Add(new GENEEOF()); SectionIO.WriteAll(stream, sections); }
private static void WriteElement(BinaryWriter writer, GOPGREC.ElementInfo elementInfo, GENESTRT stringTable, string value) { switch (elementInfo.Type) { case GOPGREC.ElementType.ENUM: writer.Write(uint.Parse(value)); break; case GOPGREC.ElementType.INT8: writer.Write(sbyte.Parse(value)); break; case GOPGREC.ElementType.INT16: writer.Write(short.Parse(value)); break; case GOPGREC.ElementType.INT32: writer.Write(int.Parse(value)); break; case GOPGREC.ElementType.UINT8: writer.Write(byte.Parse(value)); break; case GOPGREC.ElementType.UINT16: writer.Write(ushort.Parse(value)); break; case GOPGREC.ElementType.UINT32: writer.Write(uint.Parse(value)); break; case GOPGREC.ElementType.FLOAT32: writer.Write(float.Parse(value)); break; case GOPGREC.ElementType.BOOL: writer.Write(bool.Parse(value)); break; case GOPGREC.ElementType.RECID: case GOPGREC.ElementType.STRING: writer.Write(stringTable.AddString(value)); break; case GOPGREC.ElementType.RGBA: foreach (string component in StringVectorToComponents(value, 4)) { writer.Write(byte.Parse(component)); } break; case GOPGREC.ElementType.FRGB: case GOPGREC.ElementType.VECTOR3: foreach (string component in StringVectorToComponents(value, 3)) { writer.Write(float.Parse(component)); } break; case GOPGREC.ElementType.FRGBA: foreach (string component in StringVectorToComponents(value, 4)) { writer.Write(float.Parse(component)); } break; case GOPGREC.ElementType.IVECTOR4: foreach (string component in StringVectorToComponents(value, 4)) { writer.Write(int.Parse(component)); } break; default: throw new Exception("Element \"" + stringTable.Strings[(int)elementInfo.NameIndex] + "\" has unknown type " + (int)elementInfo.Type + "."); } }
private static string ReadElement(BinaryReader reader, GOPGREC.ElementInfo elementInfo, GENESTRT stringTable) { switch (elementInfo.Type) { case GOPGREC.ElementType.ENUM: return(reader.ReadUInt32().ToString()); case GOPGREC.ElementType.INT8: return(reader.ReadSByte().ToString()); case GOPGREC.ElementType.INT16: return(reader.ReadInt16().ToString()); case GOPGREC.ElementType.INT32: return(reader.ReadInt32().ToString()); case GOPGREC.ElementType.UINT8: return(reader.ReadByte().ToString()); case GOPGREC.ElementType.UINT16: return(reader.ReadUInt16().ToString()); case GOPGREC.ElementType.UINT32: return(reader.ReadUInt32().ToString()); case GOPGREC.ElementType.FLOAT32: return(reader.ReadSingle().ToString()); case GOPGREC.ElementType.BOOL: return(reader.ReadBoolean().ToString()); case GOPGREC.ElementType.RECID: case GOPGREC.ElementType.STRING: return(stringTable.Strings[reader.ReadInt32()]); case GOPGREC.ElementType.RGBA: return("(" + reader.ReadByte() + "," + reader.ReadByte() + "," + reader.ReadByte() + "," + reader.ReadByte() + ")"); case GOPGREC.ElementType.FRGB: case GOPGREC.ElementType.VECTOR3: return("(" + reader.ReadSingle() + "," + reader.ReadSingle() + "," + reader.ReadSingle() + ")"); case GOPGREC.ElementType.FRGBA: return("(" + reader.ReadSingle() + "," + reader.ReadSingle() + "," + reader.ReadSingle() + "," + reader.ReadSingle() + ")"); case GOPGREC.ElementType.IVECTOR4: return("(" + reader.ReadInt32() + "," + reader.ReadInt32() + "," + reader.ReadInt32() + "," + reader.ReadInt32() + ")"); default: throw new Exception("Element \"" + stringTable.Strings[(int)elementInfo.NameIndex] + "\" has unknown type " + (int)elementInfo.Type + "."); } }
private void WriteFiles(Stream stream, PACKTOC toc, GENESTRT nameTable) { List <Node> nodes = this.FlattenTree(this.RootDirectory); for (uint i = 0; i < nodes.Count; i++) { Node node = nodes[(int)i]; if (node is Directory dir) { PACKTOC.DirectoryEntry entry = new PACKTOC.DirectoryEntry(); entry.NameIndex = nameTable.AddString(node.Name); entry.PackageIndex = 0; entry.FirstEntryIndex = 0; entry.NumEntries = 0; for (uint j = i + 1; j < nodes.Count; j++) { Node node2 = nodes[(int)j]; if (dir.Children.Contains(node2)) { if (entry.FirstEntryIndex == 0) { entry.FirstEntryIndex = j; } entry.NumEntries++; } } toc.Entries.Add(entry); } else if (node is File file) { if (file.Compressed) { PACKTOC.CompressedFileEntry entry = new PACKTOC.CompressedFileEntry(); entry.NameIndex = nameTable.AddString(node.Name); entry.PackageIndex = 0; entry.Offset = 0; // Filled in later. entry.UncompressedSize = file.UncompressedSize; entry.CompressedSize = (ulong)file.RawData.Length; toc.Entries.Add(entry); } else { PACKTOC.UncompressedFileEntry entry = new PACKTOC.UncompressedFileEntry(); entry.NameIndex = nameTable.AddString(node.Name); entry.PackageIndex = 0; entry.Offset = 0; // Filled in later. entry.Size = (ulong)file.RawData.Length; toc.Entries.Add(entry); } stream.Write(file.RawData); stream.PadTo(0x200); } } }
public void Write(Stream stream) { GENESTRT nameTable = new GENESTRT(); nameTable.Strings.Add(this.Name); PACKHEDR packhedr = new PACKHEDR(); packhedr.Unknown1 = 0x10000; packhedr.NameIndex = 0; packhedr.DataOffset = 0; // Filled in later. packhedr.Unknown3 = 1; packhedr.Hash = new byte[16]; // TODO PACKTOC toc = new PACKTOC(); byte[] fileData; using (MemoryStream fileStream = new MemoryStream()) { this.WriteFiles(fileStream, toc, nameTable); fileData = fileStream.ToArray(); } PACKFSLS fsls = new PACKFSLS(); List <byte[]> fileSetDatas = new List <byte[]>(); uint nameIndex = (uint)nameTable.Strings.Count; foreach (FileSet fileSet in this.FileSets) { byte[] fileSetData; using (MemoryStream fileSetStream = new MemoryStream()) { this.WriteFileSet(fileSetStream, fileSet); fileSetData = fileSetStream.ToArray(); } PACKFSLS.FileSetEntry entry = new PACKFSLS.FileSetEntry(); entry.NameIndex = nameTable.AddString(fileSet.Name); entry.PackageIndex = 0; entry.Offset = 0; // Filled in later. entry.Size = (ulong)fileSetData.Length; entry.Hash = new MD5CryptoServiceProvider().ComputeHash(fileSetData); fsls.FileSets.Add(entry); fileSetDatas.Add(fileSetData); } SectionSet set = new SectionSet(); set.Add(new ENDILTLE()); set.Add(packhedr); set.Add(toc); set.Add(fsls); set.Add(nameTable); set.Add(new GENEEOF()); ulong headersSize; using (MemoryStream sizeTestStream = new MemoryStream()) { SectionIO.WriteAll(sizeTestStream, set); headersSize = (ulong)sizeTestStream.Length; } ulong currOffset = NumberUtil.Align(headersSize, 0x800); packhedr.DataOffset = (uint)currOffset; foreach (PACKTOC.Entry entry in toc.Entries) { if (entry is PACKTOC.UncompressedFileEntry uFileEntry) { uFileEntry.Offset = currOffset; currOffset = NumberUtil.Align(currOffset + uFileEntry.Size, 0x200); } else if (entry is PACKTOC.CompressedFileEntry cFileEntry) { cFileEntry.Offset = currOffset; currOffset = NumberUtil.Align(currOffset + cFileEntry.CompressedSize, 0x200); } } currOffset = NumberUtil.Align(currOffset, 0x800); foreach (PACKFSLS.FileSetEntry fileSetEntry in fsls.FileSets) { fileSetEntry.Offset = currOffset; currOffset = NumberUtil.Align(currOffset + fileSetEntry.Size, 0x800); } SectionIO.WriteAll(stream, set); stream.PadTo(0x800); stream.Write(fileData); foreach (byte[] fileSetData in fileSetDatas) { stream.PadTo(0x800); stream.Write(fileSetData); } }
private static int Main(string[] args) { OpenFileDialog fd = new OpenFileDialog(); fd.Filter = "AKB 1/48 Guam apk files|*.apk"; if (fd.ShowDialog() == DialogResult.OK) { FolderBrowserDialog fbd = new FolderBrowserDialog(); fbd.SelectedPath = "C:\\"; if (fbd.ShowDialog() == DialogResult.OK) { FileStream filestream = new FileStream("out.txt", FileMode.Create); var streamwriter = new StreamWriter(filestream); streamwriter.AutoFlush = true; Console.SetOut(streamwriter); Console.SetError(streamwriter); using (EndianBinaryReader reader = new EndianBinaryReader(EndianBitConverter.Little, File.Open(fd.FileName, FileMode.Open))) { reader.ReadBytes(16); if (Encoding.ASCII.GetString(reader.ReadBytes(8)) != "PACKHEDR") { return(-1); } PACKHEDR pkhdr = new PACKHEDR(); pkhdr.headerSize = reader.ReadInt64(); pkhdr.dummy = reader.ReadInt32(); pkhdr.zero = reader.ReadInt32(); pkhdr.dummySize = reader.ReadInt32(); pkhdr.dummy2 = reader.ReadInt32(); pkhdr.dummystring = Encoding.ASCII.GetString(reader.ReadBytes(16)); if (Encoding.ASCII.GetString(reader.ReadBytes(8)) != "PACKTOC ") { return(-1); } PACKTOC pktoc = new PACKTOC(); pktoc.size = reader.ReadInt64(); pktoc.offset = reader.BaseStream.Position; pktoc.entrySize = reader.ReadInt32(); pktoc.files = reader.ReadInt32(); pktoc.folders = reader.ReadInt32(); pktoc.zero = reader.ReadInt32(); GENESTRT gene1 = GetGENESTRT(reader, pktoc.offset, pktoc.size); //FOLDERS fldrs = new FOLDERS(pktoc.folders); for (int k = 0; k < pktoc.folders; k++) { /* * fldrs.dummystring.Add(reader.ReadBytes(pktoc.entrySize)); * fldrs.nameIdx.Add(fldrs.dummystring[k].ElementAt(4)); * fldrs.fileNum.Add(fldrs.dummystring[k].ElementAt(16)); * fldrs.subFiles.Add(fldrs.dummystring[k].ElementAt(20)); * fldrs.foldernames[k] = gene1.stringlist[fldrs.nameIdx[k]]; */ reader.ReadBytes(pktoc.entrySize); } for (int l = pktoc.folders; l < pktoc.files; l++) { long tocpos = reader.BaseStream.Position; reader.ReadInt32(); //always 0x200 (512) int idx = reader.ReadInt32(); reader.ReadInt32(); //always 0 reader.ReadInt32(); //always 0 long offset = reader.ReadInt64(); long size = reader.ReadInt64(); long zsize = reader.ReadInt64(); Console.WriteLine("TOC offset: {4} file: {0} offset: {1} size: {2} zsize: {3}", gene1.stringlist[idx], offset, size, zsize, tocpos); if (size != 0) { string fname = gene1.stringlist[idx]; if (zsize == 0) { long tmpstreampos = reader.BaseStream.Position; reader.BaseStream.Position = offset; //Console.WriteLine("File: {0} is not compressed. Writing to {1}", fname, fbd.SelectedPath + "\\" + fname); using (FileStream nfstrm = new FileStream(fbd.SelectedPath + "\\" + fname, FileMode.Create)) { nfstrm.Write(reader.ReadBytes((int)size), 0, (int)size); reader.BaseStream.Position = tmpstreampos; } } else { long tempstrmpos = reader.BaseStream.Position; reader.BaseStream.Position = offset + 2; //Console.WriteLine("File: {0} is compressed. Writing to {1}", fname, fbd.SelectedPath + "\\" + fname); MemoryStream tmpmemstrm = new MemoryStream(reader.ReadBytes((int)zsize)); using (FileStream cpfs = new FileStream(fbd.SelectedPath + "\\" + fname, FileMode.Create)) { using (DeflateStream dfstrm = new DeflateStream(tmpmemstrm, CompressionMode.Decompress)) { dfstrm.CopyTo(cpfs); } } reader.BaseStream.Position = tempstrmpos; } } } reader.BaseStream.Position = pktoc.offset + pktoc.size; if (Encoding.ASCII.GetString(reader.ReadBytes(8)) != "PACKFSLS") { return(-1); } PACKFSLS pkfls = new PACKFSLS(); pkfls.headerSize = reader.ReadInt64(); pkfls.headerOffset = reader.BaseStream.Position; pkfls.archives = reader.ReadInt32(); pkfls.dummy = reader.ReadInt32(); pkfls.dummy2 = reader.ReadInt32(); pkfls.zero = reader.ReadInt32(); for (int archive = 0; archive < pkfls.archives; archive++) { int tmpidx = reader.ReadInt32(); reader.ReadInt32(); long archiveoffset = reader.ReadInt64(); long archivesize = reader.ReadInt64(); reader.ReadBytes(16); string aname = gene1.stringlist[tmpidx]; long tmppos = reader.BaseStream.Position; extractArchives(reader, archiveoffset, aname, fbd.SelectedPath); reader.BaseStream.Position = tmppos; } } filestream.Close(); } } return(1); }
private static void extractArchives(EndianBinaryReader bread, long offset, string archname, string path) { bread.BaseStream.Position = offset; bread.ReadBytes(8); bread.ReadBytes(8); long tmppos = bread.BaseStream.Position; bread.ReadBytes(8); long header_size = bread.ReadInt64(); long header_offset = bread.BaseStream.Position; bread.ReadInt32(); int entry_size = bread.ReadInt32(); int files = bread.ReadInt32(); int entries_size = bread.ReadInt32(); bread.ReadBytes(16); GENESTRT arcgene = GetGENESTRT(bread, header_offset, header_size); for (int i = 0; i < files; i++) { int name_idx = bread.ReadInt32(); int zip = bread.ReadInt32(); long f_offset = bread.ReadInt64(); long f_size = bread.ReadInt64(); long f_zsize = bread.ReadInt64(); string f_name = archname + "/" + arcgene.stringlist[name_idx]; f_offset += offset; FileInfo fileInfo = new FileInfo(path + "/" + f_name); if (!fileInfo.Exists) { Directory.CreateDirectory(fileInfo.Directory.FullName); } if (f_zsize == 0) { long tmpstreampos = bread.BaseStream.Position; bread.BaseStream.Position = f_offset; Console.WriteLine("File: {0} is not compressed. Writing to {1}", f_name, path + "\\" + f_name); using (FileStream nfstrm = new FileStream(path + "/" + f_name, FileMode.Create)) { nfstrm.Write(bread.ReadBytes((int)f_size), 0, (int)f_size); bread.BaseStream.Position = tmpstreampos; } } else { long tempstrmpos = bread.BaseStream.Position; bread.BaseStream.Position = f_offset + 2; Console.WriteLine("File: {0} is compressed. Writing to {1}", f_name, path + "\\" + f_name); MemoryStream tmpmemstrm = new MemoryStream(bread.ReadBytes((int)f_zsize)); using (FileStream cpfs = new FileStream(path + "\\" + f_name, FileMode.Create)) { using (DeflateStream dfstrm = new DeflateStream(tmpmemstrm, CompressionMode.Decompress)) { dfstrm.CopyTo(cpfs); } } bread.BaseStream.Position = tempstrmpos; } } }