public void InsertChild(int level, ResourceEntry child) { if (level < FolderDepth) { Parent.InsertChild(level, child); } else if (level == FolderDepth) { Children.Add(child); } }
private List <ResourceEntry> LinkEntries(List <ResourceEntry> entries) { entries.Clear(); ResourceEntry tmpNode = null; foreach (ResourceEntry entry in ResourceEntries) { if (entry == null) { continue; } if (entry.FolderDepth == 1) { if (tmpNode?.Root != null) { entries.Add(tmpNode.Root); } tmpNode = entry; continue; } else if (entry.Directory) { var tmp = entry; if (entry.FolderDepth > tmpNode.FolderDepth) { tmp.Parent = tmpNode; } else if (entry.FolderDepth < tmpNode.FolderDepth) { tmp.Parent = tmpNode.Parent.Parent; } else { tmp.Parent = tmpNode.Parent; } tmpNode.InsertChild(tmp.FolderDepth - 1, tmp); tmpNode = tmp; } else { var tmp = entry; tmp.Parent = tmpNode; tmpNode.InsertChild(tmp.FolderDepth - 1, tmp); } } entries.Add(tmpNode.Root); return(entries); }
public void UpdateEntries() { VoidPtr addr = _workingSource.Address + Header.EntriesChunkOffset; uint size1 = *(uint *)addr * 8 + 4; addr += size1; uint size2 = *(uint *)addr + 4; addr += size2; for (int i = 0; i < Header.EntryCount; i++) { if (ResourceEntries[i] == null) { //ResourceEntry* entry = (ResourceEntry*)addr; //*entry = new ResourceEntry //{ // offInPack = 0xBBBBBBBB, // nameOffsetEtc = 0xBBBBBBBB, // cmpSize = 0xBBBBBBBB, // decSize = 0xBBBBBBBB, // timestamp = 0xBBBBBBBB, // flags = 0xBBBBBBBB //}; addr += 0x18; } else { ResourceEntry *entry = (ResourceEntry *)addr; *entry = new ResourceEntry { offInPack = ResourceEntries[i].OffInPack, nameOffsetEtc = ResourceEntries[i].NameOffsetEtc, cmpSize = ResourceEntries[i].CmpSize, decSize = ResourceEntries[i].DecSize, timestamp = ResourceEntries[i].Timestamp, flags = ResourceEntries[i].Flags }; addr += 0x18; } } }
public void Parse() { _s_RFHeader rfheader = *(_s_RFHeader *)WorkingSource.Address; Header = new RfHeader { Tag = rfheader._rf, RegionEtc = rfheader._regionEtc, HeaderLen1 = rfheader._headerLen1, Pad = rfheader._pad0, EntriesChunkOffset = rfheader._headerLen2, EntriesChunkLen = rfheader._0x18EntriesLen, UnixTimestamp = rfheader._unixTimestamp, CompressedLen = rfheader._compressedLen, DecompressedLen = rfheader._decompressedLen, StrsChunkOffset = rfheader._strsPlus, StrsChunkLen = rfheader._strsLen, EntryCount = rfheader._resourceEntries }; VoidPtr addr = WorkingSource.Address + Header.StrsChunkOffset; addr += *(uint *)addr * 0x2000; addr += 4; Extensions = new string[*(uint *)addr]; addr += 4; for (int i = 0; i < Extensions.Length; i++) { Extensions[i] = GetStr(*(int *)(addr + i * 4)); } addr = WorkingSource.Address + Header.EntriesChunkOffset; uint size1 = *(uint *)addr * 8 + 4; addr += size1; uint size2 = *(uint *)addr + 4; addr += size2; var entries = new List <ResourceEntry>(); for (int i = 0; i < Header.EntryCount; i++, addr += 0x18) { _s_ResourceEntry entry = *(_s_ResourceEntry *)addr; ResourceEntry rsobj = new ResourceEntry() { OffInPack = entry.offInPack, NameOffsetEtc = entry.nameOffsetEtc, CmpSize = entry.cmpSize, DecSize = entry.decSize, Timestamp = DateTimeExtension.FromUnixBytes(entry.timestamp), Flags = entry.flags, }; if (rsobj.OffInPack == 0xBBBBBBBB) { ResourceEntries.Add(null); continue; } var name = ""; if ((entry.nameOffsetEtc & 0x00800000) > 0) { var strbytes = GetStrRef((int)rsobj.NameOffset); var reference = BitConverter.ToUInt16(strbytes, 0); var reflen = (reference & 0x1f) + 4; var refoff = (reference & 0xe0) >> 6 << 8 | (reference >> 8); name = GetStr((int)rsobj.NameOffset - refoff).Remove(reflen) + GetStr((int)rsobj.NameOffset + 2); } else { name = GetStr((int)rsobj.NameOffset); } rsobj.EntryString = name + Extensions[rsobj.extIndex]; ResourceEntries.Add(rsobj); } //ResourceEntries = LinkEntries(entries); }
public void Parse(string fileDecomp) { _workingSource = new DataSource(FileMap.FromFile(fileDecomp)); RFHeader rfheader = *(RFHeader *)_workingSource.Address; Header = new RfHeaderObject { Tag = rfheader._rf, RegionEtc = rfheader._regionEtc, HeaderLen1 = rfheader._headerLen1, Pad = rfheader._pad0, EntriesChunkOffset = rfheader._headerLen2, EntriesChunkLen = rfheader._0x18EntriesLen, UnixTimestamp = rfheader._unixTimestamp, CompressedLen = rfheader._compressedLen, DecompressedLen = rfheader._decompressedLen, StrsChunkOffset = rfheader._strsPlus, StrsChunkLen = rfheader._strsLen, EntryCount = rfheader._resourceEntries }; VoidPtr addr = _workingSource.Address + Header.StrsChunkOffset; strChunks = new byte[*(uint *)addr][]; addr += 4; for (int i = 0; i < strChunks.Length; i++) { strChunks[i] = _workingSource.Slice((int)(Header.StrsChunkOffset + 4) + i * 0x2000, 0x2000); } addr += strChunks.Length * 0x2000; ExtensionOffsets = new uint[*(uint *)addr]; Extensions = new string[ExtensionOffsets.Length]; addr += 4; for (int i = 0; i < ExtensionOffsets.Length; i++) { ExtensionOffsets[i] = *(uint *)(addr + i * 4); var ext = Encoding.ASCII.GetString(str_from_offset((int)ExtensionOffsets[i], 64)); Extensions[i] = ext.Remove(ext.IndexOf('\0')); } addr = _workingSource.Address + Header.EntriesChunkOffset; uint size1 = *(uint *)addr * 8 + 4; addr += size1; uint size2 = *(uint *)addr + 4; addr += size2; ResourceEntries = new ResourceEntryObject[Header.EntryCount]; for (int i = 0; i < Header.EntryCount; i++, addr += 0x18) { ResourceEntry entry = *(ResourceEntry *)addr; ResourceEntryObject rsobj = new ResourceEntryObject() { OffInPack = entry.offInPack, NameOffsetEtc = entry.nameOffsetEtc, CmpSize = entry.cmpSize, DecSize = entry.decSize, Timestamp = entry.timestamp, Flags = entry.flags, }; if (rsobj.OffInPack == 0xBBBBBBBB) { ResourceEntries[i] = null; continue; } var strbytes = str_from_offset((int)rsobj.NameOffset, 128); var name = Encoding.ASCII.GetString(str_from_offset((int)rsobj.NameOffset, 128)); if ((entry.nameOffsetEtc & 0x00800000) > 0) { var reference = BitConverter.ToUInt16(strbytes, 0); var referenceLen = (reference & 0x1f) + 4; var refReloff = (reference & 0xe0) >> 6 << 8 | (reference >> 8); name = Encoding.ASCII.GetString(str_from_offset((int)rsobj.NameOffset - refReloff, referenceLen)) + name.Substring(2); } if (name.Contains('\0')) { name = name.Substring(0, name.IndexOf('\0')); } rsobj.EntryString = name + Extensions[rsobj.extIndex]; ResourceEntries[i] = rsobj; } //_workingSource.Close(); }
public void BuildPartitions(string folder) { if (DTFiles == null) { return; } FileStream dtstrm = File.Create("dt_rebuild"); string tmpfile = Path.GetTempFileName(); FileStream packstrm = File.Create(tmpfile); foreach (string str in Directory.EnumerateDirectories(folder)) { if (!str.Contains("data")) { return; } string partition = "resource"; if (str.Contains("(")) { partition += str.Substring(str.IndexOf("(")); } var rf = new RFFile(); LSEntry curPacked = null; int pad = 0; string packKey = ""; foreach (string key in Files.Keys) { Console.WriteLine(key); var tpl = Files[key]; if (tpl.Item2.Packed) { if (curPacked != null) { int aligned = (int)packstrm.Position.RoundUp(0x10) + 0x60; while (packstrm.Position < aligned) { packstrm.WriteByte(0xBB); } curPacked.Size = (int)packstrm.Length; LS.TrySetValue(packKey, curPacked); packstrm.WriteTo(dtstrm); packstrm.Close(); packstrm = File.Open(tmpfile, FileMode.Truncate); } curPacked = tpl.Item1; packKey = key; curPacked.DTOffset = (uint)dtstrm.Position; var data = File.ReadAllBytes($"{folder}/{key}"); for (pad = 0; pad < data.Length && data[pad] == 0xCC; pad++) { packstrm.WriteByte(0xCC); } } else if (!tpl.Item2.EntryString.EndsWith("/")) { var filedata = File.ReadAllBytes($"{folder}/{key}"); var cmp = Util.Compress(filedata); ResourceEntry rsobj = tpl.Item2; int rIndex = RF.ResourceEntries.IndexOf(rsobj); rsobj.OffInPack = (uint)packstrm.Position; rsobj.CmpSize = cmp.Length; rsobj.DecSize = filedata.Length; RF[rIndex] = rsobj; packstrm.Write(cmp, 0, cmp.Length); int aligned = (int)packstrm.Position.RoundUp(0x10) + 0x20; while (packstrm.Position % 0x10 > 0) { packstrm.WriteByte(0xCC); } } } if (curPacked != null) { curPacked.Size = (int)packstrm.Length; LS.TrySetValue(packKey, curPacked); packstrm.WriteTo(dtstrm); } RF.UpdateEntries(); byte[] full = RF.GetBytes(); var resource = LS.TryGetValue(partition); resource.DTOffset = (uint)dtstrm.Position; dtstrm.Write(full, 0, full.Length); resource.Size = full.Length; LS.TrySetValue(partition, resource); LS.UpdateEntries(); dtstrm.Close(); packstrm.Close(); } }
public void UpdateEntries() { VoidPtr addr = _workingSource.Address + Header.EntriesChunkOffset; uint size1 = *(uint*)addr * 8 + 4; addr += size1; uint size2 = *(uint*)addr + 4; addr += size2; for (int i = 0; i < Header.EntryCount; i++) { if (ResourceEntries[i] == null) { //ResourceEntry* entry = (ResourceEntry*)addr; //*entry = new ResourceEntry //{ // offInPack = 0xBBBBBBBB, // nameOffsetEtc = 0xBBBBBBBB, // cmpSize = 0xBBBBBBBB, // decSize = 0xBBBBBBBB, // timestamp = 0xBBBBBBBB, // flags = 0xBBBBBBBB //}; addr += 0x18; } else { ResourceEntry* entry = (ResourceEntry*)addr; *entry = new ResourceEntry { offInPack = ResourceEntries[i].OffInPack, nameOffsetEtc = ResourceEntries[i].NameOffsetEtc, cmpSize = ResourceEntries[i].CmpSize, decSize = ResourceEntries[i].DecSize, timestamp = ResourceEntries[i].Timestamp, flags = ResourceEntries[i].Flags }; addr += 0x18; } } }