private void readOldArkHeader(IFile hdrFile, Stream header) { root = new ArkDirectory(null, ROOT_DIR); contentFileMeta = hdrFile.GetStream(); header.Position = 8; long fileTableOffset = header.ReadUInt32LE(); uint numFiles = header.ReadUInt32LE(); long dirTableOffset = header.ReadUInt32LE(); string[] dirs = new string[header.ReadUInt32LE()]; header.Position = 0x24; long blockSize = header.ReadUInt32LE(); header.Position = dirTableOffset; for (int dir = 0; dir < dirs.Length; dir++) { header.Position = dirTableOffset + (8 * dir) + 4; header.Position = header.ReadUInt32LE(); dirs[dir] = header.ReadASCIINullTerminated(); } for (int file = 0; file < numFiles; file++) { header.Position = fileTableOffset + (24 * file) + 4; long filenameOffset = header.ReadUInt32LE(); int dir = header.ReadUInt16LE(); uint blockOffset = header.ReadUInt16LE(); uint block = header.ReadUInt32LE(); uint compressedSize = header.ReadUInt32LE(); header.Position = filenameOffset; string filename = header.ReadASCIINullTerminated(); ArkDirectory parent = dir > 0 ? makeOrGetDir(dirs[dir]) : root; parent.AddFile(new OffsetFile(filename, parent, contentFileMeta, block * blockSize + blockOffset, compressedSize)); } }
/// <summary> /// Read the filename table, which is a blob of strings, /// then read the filename pointer table which links files to filenames /// </summary> private void readFileTable(Stream header, uint version, bool brokenv4) { string[] fileNames = readFileNames(header, version != 1); if (version > 2) { // Version 3+: // Go to end of the filename pointer table which we already read // filename blob filename pointer table header.Seek(fileNameTableOffset + fileNameTableSize + 4 + 4 * numFileNames, SeekOrigin.Begin); } else { // Version 2: still at beginning of file. (after version number ofc) header.Seek(4, SeekOrigin.Begin); } // Now the number of *actual* files in the archive. // Directories are not explicitly stored. Rather, they are inferred // by the path string each file has, which tells you in which folder // the file lives. uint numFiles = header.ReadUInt32LE(); for (var i = 0; i < numFiles; i++) { // Version 3 uses 32-bit file offsets long arkFileOffset = 0; if (version != 1) { arkFileOffset = (brokenv4 || version <= 3 ? header.ReadUInt32LE() : header.ReadInt64LE()); } int filenameStringId = header.ReadInt32LE(); int dirStringId = header.ReadInt32LE(); if (version == 1) { arkFileOffset = header.ReadUInt32LE(); } uint size = header.ReadUInt32LE(); uint zero = header.ReadUInt32LE(); // Version 7 uses this differently. now, files marked as 0 should be skipped, // while NON-zero values mean real files. I think. if ((version == 7 && zero != 0) || (version != 7 && zero == 0)) { ArkDirectory parent = dirStringId > 0 ? makeOrGetDir(fileNames[dirStringId]) : root; parent.AddFile(new OffsetFile(fileNames[filenameStringId], parent, contentFileMeta, arkFileOffset, size)); } } }