コード例 #1
0
ファイル: RFFile.cs プロジェクト: volt72/Sm4sh-Tools
 public void InsertChild(int level, ResourceEntry child)
 {
     if (level < FolderDepth)
     {
         Parent.InsertChild(level, child);
     }
     else if (level == FolderDepth)
     {
         Children.Add(child);
     }
 }
コード例 #2
0
ファイル: RFFile.cs プロジェクト: volt72/Sm4sh-Tools
        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);
        }
コード例 #3
0
        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;
                }
            }
        }
コード例 #4
0
        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);
        }
コード例 #5
0
        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();
        }
コード例 #6
0
        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();
            }
        }
コード例 #7
0
ファイル: RFFile.cs プロジェクト: soneek/Sm4sh-Tools
        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;
                }
            }
        }