protected override void _Write(BinaryWriter writer) { long baseOffset = writer.BaseStream.Position; FileCount = (uint)Entries.Count; writer.Write(Signature); writer.Write(FileCount); //Calculate offsets uint startOffset = 8 + FileCount * 16; startOffset = startOffset + 0x0800 - (startOffset % 0x0800); if (FileCount > 1016) { startOffset = 0x0008000; } uint offset = startOffset; for (int i = 0; i < Entries.Count; i++) { AFSEntry entry = Entries[i]; entry.Index = (uint)i; entry.Offset = offset; offset += entry.FileSize; offset += SectorSize - (offset % SectorSize); //sector padding } //Write offsets foreach (AFSEntry entry in Entries) { entry.WriteOffset(writer); } //Calculate and write filename table offset FilenameSectionOffset = offset; FilenameSectionSize = (uint)Entries.Count * AFSEntry.Length; writer.BaseStream.Seek(baseOffset + startOffset - 8, SeekOrigin.Begin); writer.Write(FilenameSectionOffset); writer.Write(FilenameSectionSize); //Write data foreach (AFSEntry entry in Entries) { writer.BaseStream.Seek(baseOffset + entry.Offset, SeekOrigin.Begin); entry.WriteData(writer); } //Write filenames writer.BaseStream.Seek(baseOffset + FilenameSectionOffset, SeekOrigin.Begin); foreach (AFSEntry entry in Entries) { entry.WriteFilename(writer); } }
public void Pack(List <string> filepaths) { Entries.Clear(); foreach (string filepath in filepaths) { FileInfo fileInfo = new FileInfo(filepath); AFSEntry entry = new AFSEntry(); entry.Filename = Path.GetFileNameWithoutExtension(filepath); entry.EntryDateTime = fileInfo.LastWriteTimeUtc; using (FileStream stream = new FileStream(filepath, FileMode.Open)) { entry.FileSize = (uint)stream.Length; entry.Buffer = new byte[stream.Length]; stream.Read(entry.Buffer, 0, entry.Buffer.Length); } Entries.Add(entry); } }
protected override void _Read(BinaryReader reader) { long baseOffset = reader.BaseStream.Position; Signature = reader.ReadUInt32(); if (!IsValid(Signature)) { throw new InvalidFileSignatureException(); } FileCount = reader.ReadUInt32(); Entries.Clear(); //read file offsets (table of content) uint index = 0; for (int i = 0; i < FileCount; i++) { AFSEntry entry = new AFSEntry(); entry.ReadOffset(reader); entry.Index = index; Entries.Add(entry); index++; } //Read filename table offset //This limit is just a guess, needs testing if (FileCount > 1016) { reader.BaseStream.Seek(baseOffset + 0x0008000 - 8, SeekOrigin.Begin); FilenameSectionOffset = reader.ReadUInt32(); FilenameSectionSize = reader.ReadUInt32(); } else { long offset = reader.BaseStream.Position + 0x0800 - (reader.BaseStream.Position % 0x0800); reader.BaseStream.Seek(baseOffset + offset - 8, SeekOrigin.Begin); FilenameSectionOffset = reader.ReadUInt32(); FilenameSectionSize = reader.ReadUInt32(); } if (FilenameSectionOffset == 0) { //Set incrementing filenames if table of content is missing. for (int i = 0; i < FileCount; i++) { Entries[i].Filename = "file_" + i; } } else { //Read table of contents reader.BaseStream.Seek(baseOffset + FilenameSectionOffset, SeekOrigin.Begin); for (int i = 0; i < FileCount; i++) { Entries[i].ReadFilename(reader); } } //Read file data foreach (AFSEntry entry in Entries) { reader.BaseStream.Seek(baseOffset + entry.Offset, SeekOrigin.Begin); entry.ReadData(reader); } if (AutomaticLoadIDX) { if (typeof(FileStream).IsAssignableFrom(reader.BaseStream.GetType())) { FileStream fs = (FileStream)reader.BaseStream; string idxPath = Path.ChangeExtension(fs.Name, ".IDX"); if (File.Exists(idxPath)) { IDX idx = new IDX(idxPath); MapIDXFile(idx); } } } }