/** * Creates and returns a new FST Entry * @return */ public static FSTEntry getRootFSTEntry() { FSTEntryParam param = new FSTEntryParam(); param.isRoot = true; param.isDir = true; return(new FSTEntry(param)); }
public FSTEntry(FSTEntryParam fstParam) { this.filename = fstParam.Filename; this.path = fstParam.Path; this.flags = fstParam.Flags; this.parent = fstParam.Parent; if (parent != null) { parent.Children.Add(this); } this.fileSize = fstParam.FileSize; this.fileOffset = fstParam.FileOffset; this.content = fstParam.Content; if (content != null) { content.addEntry(this); } this.isDir = fstParam.isDir; this.isRoot = fstParam.isRoot; this.isNotInPackage = fstParam.notInPackage; this.contentFSTID = fstParam.ContentFSTID; }
public static void parseFST(FSTEntry rootEntry, byte[] fstSection, byte[] namesSection, Dictionary <int, Content> contentsByIndex, Dictionary <int, ContentFSTInfo> contentsFSTByIndex) { int totalEntries = Utils.SwapEndianness(BitConverter.ToInt32(fstSection, 0x08)); int level = 0; int[] LEntry = new int[16]; int[] Entry = new int[16]; String[] pathStrings = new String[16]; for (int i = 0; i < 16; i++) { pathStrings[i] = ""; } Dictionary <int, FSTEntry> fstEntryToOffsetMap = new Dictionary <int, FSTEntry>(); Entry[level] = 0; LEntry[level++] = 0; fstEntryToOffsetMap.Add(0, rootEntry); int lastlevel = level; String path = "\\"; FSTEntry last = null; for (int i = 1; i < totalEntries; i++) { int entryOffset = i; if (level > 0) { while (LEntry[level - 1] == i) { level--; } } byte[] curEntry = Arrays.copyOfRange(fstSection, i * 0x10, (i + 1) * 0x10); FSTEntryParam entryParam = new FSTEntryParam(); if (lastlevel != level) { path = pathStrings[level] + getFullPath(level - 1, level, fstSection, namesSection, Entry); lastlevel = level; } String filename = getName(curEntry, namesSection); long fileOffset = Utils.SwapEndianness(BitConverter.ToInt32(curEntry, 0x04)); long fileSize = (uint)Utils.SwapEndianness(BitConverter.ToInt32(curEntry, 0x08)); short flags = Utils.SwapEndianness(BitConverter.ToInt16(curEntry, 0x0C)); short contentIndex = Utils.SwapEndianness(BitConverter.ToInt16(curEntry, 0x0E)); if ((curEntry[0] & FSTEntry.FSTEntry_notInNUS) == FSTEntry.FSTEntry_notInNUS) { entryParam.notInPackage = (true); } FSTEntry parent = null; if ((curEntry[0] & FSTEntry.FSTEntry_DIR) == FSTEntry.FSTEntry_DIR) { entryParam.isDir = (true); int parentOffset = (int)fileOffset; int nextOffset = (int)fileSize; parent = fstEntryToOffsetMap[parentOffset]; Entry[level] = i; LEntry[level++] = nextOffset; pathStrings[level] = path; if (level > 15) { //MessageBox.Show("level > 15"); break; } } else { entryParam.FileOffset = (fileOffset << 5); entryParam.FileSize = (fileSize); parent = fstEntryToOffsetMap[(Entry[level - 1])]; } entryParam.Flags = (flags); entryParam.Filename = (filename); entryParam.Path = (path); if (contentsByIndex != null) { Content content = contentsByIndex[contentIndex]; if (content == null) { //MessageBox.Show("Content for FST Entry not found"); } else { if (content.isHashed() && (content.getDecryptedFileSize() < (fileOffset << 5))) { // TODO: Figure out how this works... entryParam.FileOffset = (fileOffset); } entryParam.Content = (content); ContentFSTInfo contentFSTInfo = contentsFSTByIndex[(int)contentIndex]; if (contentFSTInfo == null) { //MessageBox.Show("ContentFSTInfo for FST Entry not found"); } else { content.contentFSTInfo = (contentFSTInfo); } } } entryParam.ContentFSTID = (contentIndex); entryParam.Parent = (parent); FSTEntry entry = new FSTEntry(entryParam); last = entry; fstEntryToOffsetMap.Add(entryOffset, entry); } }