public void ReadRawToc(byte[] rawToc) { containerCount = ByteTools.ReadUInt(rawToc, 0x10); if (containerCount > 0xFFFF) { ByteTools.bigEndian = true; containerCount = ByteTools.ReadUInt(rawToc, 0x10); } tableOffset = ByteTools.ReadUInt(rawToc, 0x14); namesOffset = ByteTools.ReadUInt(rawToc, 0x18); string[] entryNames = Encoding.ASCII.GetString(rawToc, (int)namesOffset, (int)(rawToc.Length - namesOffset)).Split(new char[] { (char)0 }); entries = new tocEntryStruct[entryNames.Length]; for (int i = 0; i < entries.Length; i++) { tocEntryStruct newTocEntry = new tocEntryStruct { nameChecksum = ByteTools.ReadUInt(rawToc, (int)(tableOffset + i * 24 + 0)), isFolder = ByteTools.ReadBoolean(rawToc, (int)(tableOffset + i * 24 + 4)), container = ByteTools.ReadUInt(rawToc, (int)(tableOffset + i * 24 + 8)), offset = ByteTools.ReadUInt(rawToc, (int)(tableOffset + i * 24 + 12)), length = ByteTools.ReadUInt(rawToc, (int)tableOffset + i * 24 + 16), name = entryNames[i] }; entries[i] = newTocEntry; } }
public static void Unpack(Toc toc, uint tocIndex, string packagePath, string inDirectoryPath, string outDirectoryPath) { if (abort) { return; } tocEntryStruct tocEntry = toc.entries[tocIndex]; if (tocEntry.isFolder) { if (tocIndex == 0) { outDirectoryPath = JoinPaths(outDirectoryPath, toc.name); } else { packagePath = JoinPaths(packagePath, tocEntry.name); } Directory.CreateDirectory(JoinPaths(outDirectoryPath, packagePath)); for (uint i = 0; i < tocEntry.length; i++) { Unpack(toc, tocEntry.offset + i, packagePath, inDirectoryPath, outDirectoryPath); } } else { SetStatusText(JoinPaths(packagePath, tocEntry.name)); string inFilePath = string.Format("{0}/{1}.M{2:00}", inDirectoryPath, toc.name, tocEntry.container); string outFilePath = JoinPaths(outDirectoryPath, packagePath, Path.GetFileNameWithoutExtension(tocEntry.name)); CheckFileExists(inFilePath); if (abort) { return; } byte[] fileBytes = ExtractFile(inFilePath, tocEntry.offset, tocEntry.length); if (Path.GetExtension(tocEntry.name) == ".stz") { Stz StzFile = new Stz(Path.GetFileNameWithoutExtension(tocEntry.name), fileBytes); SafeFileWrite(outFilePath + ".dat", StzFile.data[3]); if (!abort) { SafeFileWrite(outFilePath + ".rel", StzFile.data[4]); } } else { SafeFileWrite(outFilePath + Path.GetExtension(tocEntry.name), fileBytes); } progress += tocEntry.length; SetProgressBarValue((int)((100 * progress) / packageSize)); } }
private void PrintToFile(long tocIndex, string currentPath) { tocEntryStruct tocEntry = entries[tocIndex]; if (!tocEntry.isFolder) { textFile.WriteLine("{0}{1}\tM{2:00}\t{3:X}\t{4}\t{5:X}", currentPath, tocEntry.name, tocEntry.container, tocEntry.offset, tocEntry.length, tocEntry.nameChecksum); } else { for (int i = 0; i < tocEntry.length; i++) { PrintToFile(tocEntry.offset + i, currentPath + tocEntry.name + "/"); } } }
public static long GetPackageSize(Toc toc, uint tocIndex) { tocEntryStruct tocEntry = toc.entries[tocIndex]; if (tocEntry.isFolder) { long size = 0; for (uint i = 0; i < tocEntry.length; i++) { size += GetPackageSize(toc, tocEntry.offset + i); } return(size); } else { return(tocEntry.length); } }
public byte[] CreateRawToc() { int nameStringLength = entries.Length - 1; foreach (tocEntryStruct tocEntry in entries) { nameStringLength += tocEntry.name.Length; } byte[] rawToc = new byte[namesOffset + nameStringLength]; ByteTools.WriteBytes(rawToc, 0, tocIdentifier); ByteTools.WriteUInt(rawToc, 0x10, containerCount); ByteTools.WriteUInt(rawToc, 0x14, tableOffset); ByteTools.WriteUInt(rawToc, 0x18, namesOffset); string namesString = ""; for (int i = 0; i < entries.Length; i++) { tocEntryStruct tocEntry = entries[i]; ByteTools.WriteUInt(rawToc, tableOffset + i * 24 + 0, tocEntry.nameChecksum); ByteTools.WriteUInt(rawToc, tableOffset + i * 24 + 4, tocEntry.isFolder ? 1u : 0u); ByteTools.WriteUInt(rawToc, tableOffset + i * 24 + 8, tocEntry.container); ByteTools.WriteUInt(rawToc, tableOffset + i * 24 + 12, tocEntry.offset); ByteTools.WriteUInt(rawToc, tableOffset + i * 24 + 16, tocEntry.length); ByteTools.WriteUInt(rawToc, tableOffset + i * 24 + 20, (uint)(namesString.Length)); namesString += tocEntry.name; if (i < entries.Length - 1) { namesString += (char)0; } ; } ByteTools.WriteString(rawToc, namesOffset, namesString); return(rawToc); }
public static uint Pack(Toc toc, uint tocIndex, uint tocOffset, DirectoryInfo currentInDirectory, string outDirectoryPath) { if (abort) { return(0); } DirectoryInfo[] subDirectories = currentInDirectory.GetDirectories(); FileInfo[] files = currentInDirectory.GetFiles(); uint itemCount = (uint)(subDirectories.Length + files.Length); tocEntryStruct tocEntry = new tocEntryStruct() { isFolder = true, length = itemCount, offset = tocOffset }; if (tocIndex == 0) { tocEntry.name = ""; tocEntry.nameChecksum = 0; tocEntry.container = uint.MaxValue; } else { tocEntry.name = currentInDirectory.Name; tocEntry.nameChecksum = CryptTools.GetNameChecksum(currentInDirectory.Name); } toc.entries[tocIndex] = tocEntry; uint i = 0; foreach (DirectoryInfo subDirectory in subDirectories) { itemCount += Pack(toc, tocOffset + i, tocOffset + itemCount, subDirectory, outDirectoryPath); toc.entries[tocOffset + i].container = tocIndex; i++; } foreach (FileInfo file in files) { SetStatusText(file.FullName.Substring(inDirectoryPathLength, file.FullName.Length - inDirectoryPathLength)); string outFilePath = JoinPaths(outDirectoryPath, string.Format("{0}.M{1:00}", toc.name, toc.containerCount - 1)); if (toc.containerCount == 0 || (new FileInfo(outFilePath).Length) + file.Length > uint.MaxValue) { toc.containerCount++; outFilePath = JoinPaths(outDirectoryPath, string.Format("{0}.M{1:00}", toc.name, toc.containerCount - 1)); SafeFileWrite(outFilePath, new byte[0]); if (abort) { return(0); } } byte[] fileBytes = File.ReadAllBytes(file.FullName); string inFilePath = file.FullName; toc.entries[tocOffset + i] = new tocEntryStruct() { isFolder = false, length = (uint)file.Length, name = Path.GetFileName(inFilePath), nameChecksum = CryptTools.GetNameChecksum(Path.GetFileName(inFilePath)), offset = (uint)(new FileInfo(outFilePath).Length), container = toc.containerCount - 1 }; AppendFile(outFilePath, fileBytes); progress += file.Length; SetProgressBarValue((int)((100 * progress) / packageSize)); i++; } return(itemCount); }