Esempio n. 1
0
        /// <summary>
        /// Opens dat file from stream
        /// </summary>
        /// <param name="stream"></param>
        public void Open(Stream stream)
        {
            using (BinaryReaderExt r = new BinaryReaderExt(stream))
            {
                r.BigEndian = true;

                Stopwatch sw = new Stopwatch();

                sw.Start();

                // Parse Header -----------------------------
                var fsize       = r.ReadInt32(); // dat size
                int relocOffset = r.ReadInt32() + 0x20;
                int relocCount  = r.ReadInt32();
                int rootCount   = r.ReadInt32();
                int refCount    = r.ReadInt32();
                VersionChars = r.ReadChars(4);

                // Parse Relocation Table -----------------------------
                List <int>            Offsets       = new List <int>();
                HashSet <int>         OffsetContain = new HashSet <int>();
                Dictionary <int, int> relocOffsets  = new Dictionary <int, int>();
                Offsets.Add(relocOffset);

                for (int i = 0; i < relocCount; i++)
                {
                    r.BaseStream.Position = relocOffset + 4 * i;
                    int offset = r.ReadInt32() + 0x20;

                    r.BaseStream.Position = offset;

                    var objectOff = r.ReadInt32() + 0x20;

                    // if we need to read past end of file then we need to include filesize as an offset
                    // this fixes files that had previously been manually relocated to end of file
                    if (objectOff > relocOffset && !OffsetContain.Contains(fsize))
                    {
                        Offsets.Add(fsize);
                    }

                    // alternate null pointer
                    if (objectOff < 0)
                    {
                        continue;
                    }

                    relocOffsets.Add(offset, objectOff);

                    if (!OffsetContain.Contains(objectOff))
                    {
                        OffsetContain.Add(objectOff);
                        Offsets.Add(objectOff);
                    }
                }

                Debug.WriteLine("Relocate Parsed: " + sw.ElapsedMilliseconds);
                sw.Restart();

                // Parse Roots---------------------------------
                r.BaseStream.Position = relocOffset + relocCount * 4;
                List <int>    rootOffsets = new List <int>();
                List <string> rootStrings = new List <string>();
                List <int>    refOffsets  = new List <int>();
                List <string> refStrings  = new List <string>();
                var           stringStart = r.BaseStream.Position + (refCount + rootCount) * 8;
                for (int i = 0; i < rootCount; i++)
                {
                    rootOffsets.Add(r.ReadInt32() + 0x20);
                    rootStrings.Add(r.ReadString((int)stringStart + r.ReadInt32(), -1));
                }
                for (int i = 0; i < refCount; i++)
                {
                    var refp = r.ReadInt32() + 0x20;
                    refOffsets.Add(refp);
                    refStrings.Add(r.ReadString((int)stringStart + r.ReadInt32(), -1));

                    var temp = r.Position;

                    var special = refp;
                    while (true)
                    {
                        r.Seek((uint)special);
                        special = r.ReadInt32();

                        if (special == 0 || special == -1)
                        {
                            break;
                        }

                        special += 0x20;

                        relocOffsets.Add(refp, special);

                        refp = special;

                        if (!OffsetContain.Contains(special))
                        {
                            OffsetContain.Add(special);
                            Offsets.Add(special);
                        }
                    }

                    r.Seek(temp);
                }
                foreach (var v in rootOffsets)
                {
                    if (!OffsetContain.Contains(v))
                    {
                        OffsetContain.Add(v);
                        Offsets.Add(v);
                    }
                }
                foreach (var v in refOffsets)
                {
                    if (!OffsetContain.Contains(v))
                    {
                        OffsetContain.Add(v);
                        Offsets.Add(v);
                    }
                }


                Debug.WriteLine("Roots Parsed: " + sw.ElapsedMilliseconds);
                sw.Restart();
                // Split Raw Struct Data--------------------------
                Offsets.Sort();

                Debug.WriteLine("Sorted: " + sw.ElapsedMilliseconds);
                sw.Restart();

                Dictionary <int, HSDStruct>   offsetToStruct       = new Dictionary <int, HSDStruct>();
                Dictionary <int, List <int> > offsetToOffsets      = new Dictionary <int, List <int> >();
                Dictionary <int, List <int> > offsetToInnerOffsets = new Dictionary <int, List <int> >();

                var relockeys = relocOffsets.Keys.ToList();
                relockeys.Sort();
                for (int i = 0; i < Offsets.Count - 1; i++)
                {
                    r.BaseStream.Position = Offsets[i];
                    byte[] data = r.ReadBytes(Offsets[i + 1] - Offsets[i]);

                    if (!offsetToOffsets.ContainsKey(Offsets[i]))
                    {
                        var relocKets = new List <int>();
                        var list      = new List <int>();
                        var min       = BinarySearch(relockeys, Offsets[i]);
                        var max       = BinarySearch(relockeys, Offsets[i + 1]) + 1;

                        if (min != -1 && max != -1)
                        {
                            for (int v = min; v < max; v++)
                            {
                                if (relockeys[v] >= Offsets[i] && relockeys[v] < Offsets[i + 1])
                                {
                                    relocKets.Add(relockeys[v]);
                                    list.Add(relocOffsets[relockeys[v]]);
                                }
                            }
                        }

                        offsetToOffsets.Add(Offsets[i], list);
                        offsetToInnerOffsets.Add(Offsets[i], relocKets);
                    }

                    if (!offsetToStruct.ContainsKey(Offsets[i]))
                    {
                        var struture = new HSDStruct(data);

                        offsetToStruct.Add(Offsets[i], struture);
                    }
                }
                Debug.WriteLine("Find All Parsed: " + sw.ElapsedMilliseconds);
                sw.Restart();

                HashSet <HSDStruct> orphans = new HashSet <HSDStruct>();

                foreach (var str in offsetToStruct)
                {
                    orphans.Add(str.Value);
                }

                // set references-------------------------
                foreach (var str in offsetToStruct)
                {
                    var _o = str.Key;
                    var _s = str.Value;

                    var offsets      = offsetToOffsets[_o];
                    var innerOffsets = offsetToInnerOffsets[_o];

                    // set references in struct
                    for (int i = 0; i < offsets.Count; i++)
                    {
                        if (offsetToStruct.ContainsKey(offsets[i]) && _s.Length >= innerOffsets[i] - _o + 4)
                        {
                            var refstruct = offsetToStruct[offsets[i]];

                            _s.SetReferenceStruct(innerOffsets[i] - _o, refstruct);

                            // this not is not an orphan
                            if (refstruct != _s && orphans.Contains(refstruct))
                            {
                                orphans.Remove(refstruct);
                            }
                        }
                    }

                    _structCache.Add(str.Value);
                    _structCacheToOffset.Add(str.Value, str.Key);
                }

                Debug.WriteLine("Set References: " + sw.ElapsedMilliseconds);
                sw.Restart();

                // set roots
                for (int i = 0; i < rootOffsets.Count; i++)
                {
                    HSDStruct   str = offsetToStruct[rootOffsets[i]];
                    HSDAccessor a   = GuessAccessor(rootStrings[i], str);

                    Roots.Add(new HSDRootNode()
                    {
                        Name = rootStrings[i], Data = a
                    });

                    if (orphans.Contains(str))
                    {
                        orphans.Remove(str);
                    }
                }


                // set references
                for (int i = 0; i < refOffsets.Count; i++)
                {
                    HSDStruct   str = offsetToStruct[refOffsets[i]];
                    HSDAccessor a   = new HSDAccessor();
                    a._s = str;
                    References.Add(new HSDRootNode()
                    {
                        Name = refStrings[i], Data = a
                    });

                    if (orphans.Contains(str))
                    {
                        orphans.Remove(str);
                    }
                }

                // process special orphans
                foreach (var orphan in orphans)
                {
                    HSDStruct   str = orphan;
                    HSDAccessor a   = new HSDAccessor()
                    {
                        _s = str
                    };

                    // hack: if this is a subaction append it to previous struct
                    if (str.References.Count > 0)
                    {
                        var maxkey = str.References.Keys.Max();
                        if (str.References[maxkey] == str && maxkey >= 8 && str.GetInt32(maxkey - 4) == 0x1C000000)
                        {
                            // get previous struct
                            var prev = GetPreviousStruct(str);

                            // add goto pointer to subaction
                            if (prev != null)
                            {
                                var len = prev.Length;
                                prev.Resize(prev.Length + 8);
                                prev.SetInt32(len, 0x1C000000);
                                prev.SetReferenceStruct(len + 4, str);
                                continue;
                            }
                        }
                    }

#if DEBUG
                    // add orphans for debugging
                    Roots.Add(new HSDRootNode()
                    {
                        Name = "Orphan0x" + _structCacheToOffset[orphan].ToString("X"), Data = a
                    });
#endif
                }

                Debug.WriteLine("Finish: " + sw.ElapsedMilliseconds);
                sw.Restart();
            }
        }
Esempio n. 2
0
        /// <summary>
        /// Opens dat file from stream
        /// </summary>
        /// <param name="stream"></param>
        public void Open(Stream stream)
        {
            using (BinaryReaderExt r = new BinaryReaderExt(stream))
            {
                r.BigEndian = true;

                // Parse Header -----------------------------
                var fsize       = r.ReadInt32(); // dat size
                int relocOffset = r.ReadInt32() + 0x20;
                int relocCount  = r.ReadInt32();
                int rootCount   = r.ReadInt32();
                int refCount    = r.ReadInt32();
                VersionChars = r.ReadChars(4);

                // Parse Relocation Table -----------------------------
                List <int>            Offsets       = new List <int>();
                HashSet <int>         OffsetContain = new HashSet <int>();
                Dictionary <int, int> relocOffsets  = new Dictionary <int, int>();
                Offsets.Add(relocOffset);

                r.BaseStream.Position = relocOffset;
                for (int i = 0; i < relocCount; i++)
                {
                    int offset = r.ReadInt32() + 0x20;

                    var temp = r.BaseStream.Position;

                    r.BaseStream.Position = offset;

                    var objectOff = r.ReadInt32() + 0x20;

                    // if we need to read past end of file then we need to include filesize as an offset
                    // this fixes files that had previously been manually relocated to end of file
                    if (objectOff > relocOffset && !Offsets.Contains(fsize))
                    {
                        Offsets.Add(fsize);
                    }

                    //
                    if (objectOff < 0)
                    {
                        r.BaseStream.Position = temp;
                        continue;
                    }

                    relocOffsets.Add(offset, objectOff);

                    if (!OffsetContain.Contains(objectOff))
                    {
                        OffsetContain.Add(objectOff);
                        Offsets.Add(objectOff);
                    }

                    r.BaseStream.Position = temp;
                }

                // Parse Roots---------------------------------
                List <int>    rootOffsets = new List <int>();
                List <string> rootStrings = new List <string>();
                List <int>    refOffsets  = new List <int>();
                List <string> refStrings  = new List <string>();
                var           stringStart = r.BaseStream.Position + (refCount + rootCount) * 8;
                for (int i = 0; i < rootCount; i++)
                {
                    rootOffsets.Add(r.ReadInt32() + 0x20);
                    rootStrings.Add(r.ReadString((int)stringStart + r.ReadInt32(), -1));
                }
                for (int i = 0; i < refCount; i++)
                {
                    var refp = r.ReadInt32() + 0x20;
                    refOffsets.Add(refp);
                    refStrings.Add(r.ReadString((int)stringStart + r.ReadInt32(), -1));

                    var temp = r.Position;

                    var special = refp;
                    while (true)
                    {
                        r.Seek((uint)special);
                        special = r.ReadInt32();

                        if (special == 0 || special == -1)
                        {
                            break;
                        }

                        special += 0x20;

                        relocOffsets.Add(refp, special);

                        refp = special;

                        if (!OffsetContain.Contains(special))
                        {
                            OffsetContain.Add(special);
                            Offsets.Add(special);
                        }
                    }

                    r.Seek(temp);
                }
                foreach (var v in rootOffsets)
                {
                    if (!OffsetContain.Contains(v))
                    {
                        OffsetContain.Add(v);
                        Offsets.Add(v);
                    }
                }
                foreach (var v in refOffsets)
                {
                    if (!OffsetContain.Contains(v))
                    {
                        OffsetContain.Add(v);
                        Offsets.Add(v);
                    }
                }


                // Split Raw Struct Data--------------------------
                Offsets.Sort();

                Dictionary <int, HSDStruct>   offsetToStruct       = new Dictionary <int, HSDStruct>();
                Dictionary <int, List <int> > offsetToOffsets      = new Dictionary <int, List <int> >();
                Dictionary <int, List <int> > offsetToInnerOffsets = new Dictionary <int, List <int> >();

                var relockeys = relocOffsets.Keys.ToList();
                for (int i = 0; i < Offsets.Count - 1; i++)
                {
                    r.BaseStream.Position = Offsets[i];
                    byte[] data = r.ReadBytes(Offsets[i + 1] - Offsets[i]);

                    if (!offsetToOffsets.ContainsKey(Offsets[i]))
                    {
                        var relocKets = relockeys.FindAll(e => e >= Offsets[i] && e < Offsets[i + 1]);
                        var list      = new List <int>();
                        foreach (var k in relocKets)
                        {
                            list.Add(relocOffsets[k]);
                        }
                        offsetToOffsets.Add(Offsets[i], list);
                        offsetToInnerOffsets.Add(Offsets[i], relocKets);
                    }

                    if (!offsetToStruct.ContainsKey(Offsets[i]))
                    {
                        var struture = new HSDStruct(data);

                        offsetToStruct.Add(Offsets[i], struture);
                    }
                }

                // set references-------------------------
                foreach (var str in offsetToStruct)
                {
                    var offsets      = offsetToOffsets[str.Key];
                    var innerOffsets = offsetToInnerOffsets[str.Key];
                    for (int i = 0; i < offsets.Count; i++)
                    {
                        if (offsetToStruct.ContainsKey(offsets[i]) && str.Value.Length >= innerOffsets[i] - str.Key + 4)
                        {
                            str.Value.SetReferenceStruct(innerOffsets[i] - str.Key, offsetToStruct[offsets[i]]);
                        }
                    }

                    _structCache.Add(str.Value);
                    _structCacheToOffset.Add(str.Value, str.Key);
                }

                // set roots
                for (int i = 0; i < rootOffsets.Count; i++)
                {
                    HSDStruct   str = offsetToStruct[rootOffsets[i]];
                    HSDAccessor a   = new HSDAccessor();
                    a._s = str;
                    if (rootStrings[i].EndsWith("shapeanim_joint"))
                    {
                        var acc = new HSDAccessor();
                        acc._s = str;
                        a      = acc;
                    }
                    else
                    if (rootStrings[i].EndsWith("matanim_joint"))
                    {
                        var acc = new HSD_MatAnimJoint();
                        acc._s = str;
                        a      = acc;
                    }
                    else
                    if (rootStrings[i].EndsWith("_joint"))
                    {
                        var jobj = new HSD_JOBJ();
                        jobj._s = str;
                        a       = jobj;
                    }
                    else
                    if (rootStrings[i].EndsWith("_animjoint"))
                    {
                        var jobj = new HSD_AnimJoint();
                        jobj._s = str;
                        a       = jobj;
                    }
                    else
                    if (rootStrings[i].EndsWith("_texanim"))
                    {
                        var jobj = new HSD_TexAnim();
                        jobj._s = str;
                        a       = jobj;
                    }
                    else
                    if (rootStrings[i].EndsWith("_figatree"))
                    {
                        var jobj = new HSD_FigaTree();
                        jobj._s = str;
                        a       = jobj;
                    }
                    else
                    if (rootStrings[i].EndsWith("_scene_models") ||
                        rootStrings[i].Equals("Stc_rarwmdls") ||
                        rootStrings[i].Equals("Stc_scemdls") ||
                        rootStrings[i].Equals("lupe") ||
                        rootStrings[i].Equals("tdsce"))
                    {
                        var jobj = new HSDNullPointerArrayAccessor <HSD_JOBJDesc>();
                        jobj._s = str;
                        a       = jobj;
                    }
                    else
                    if (rootStrings[i].StartsWith("ftData"))
                    {
                        var acc = new SBM_PlayerData();
                        acc._s = str;
                        a      = acc;
                    }
                    else
                    if (rootStrings[i].EndsWith("MnSelectChrDataTable"))
                    {
                        var acc = new SBM_SelectChrDataTable();
                        acc._s = str;
                        a      = acc;
                    }
                    else
                    if (rootStrings[i].EndsWith("MnSelectStageDataTable"))
                    {
                        var acc = new SBM_MnSelectStageDataTable();
                        acc._s = str;
                        a      = acc;
                    }
                    else
                    if (rootStrings[i].EndsWith("coll_data"))
                    {
                        var acc = new SBM_Coll_Data();
                        acc._s = str;
                        a      = acc;
                    }
                    else
                    if (rootStrings[i].EndsWith("scene_data") ||
                        rootStrings[i].Equals("pnlsce") ||
                        rootStrings[i].Equals("flmsce") ||
                        (rootStrings[i].StartsWith("Sc") && str.Length == 0x10))
                    {
                        var acc = new HSD_SOBJ();
                        acc._s = str;
                        a      = acc;
                    }
                    else
                    if (rootStrings[i].StartsWith("map_plit"))
                    {
                        var acc = new HSDNullPointerArrayAccessor <HSD_Light>();
                        acc._s = str;
                        a      = acc;
                    }

                    /*else
                     * if (rootStrings[i].StartsWith("grGroundParam"))
                     * {
                     *  var acc = new SBM_GroundParam();
                     *  acc._s = str;
                     *  a = acc;
                     * }*/
                    else
                    if (rootStrings[i].StartsWith("map_head"))
                    {
                        var acc = new SBM_Map_Head();
                        acc._s = str;
                        a      = acc;
                    }
                    else
                    if (rootStrings[i].StartsWith("grGroundParam"))
                    {
                        var acc = new SBM_GroundParam();
                        acc._s = str;
                        a      = acc;
                    }
                    else
                    if (rootStrings[i].StartsWith("vcDataStar"))
                    {
                        var acc = new KAR_vcDataStar();
                        acc._s = str;
                        a      = acc;
                    }
                    else
                    if (rootStrings[i].StartsWith("vcDataWheel"))
                    {
                        var acc = new KAR_vcDataWheel();
                        acc._s = str;
                        a      = acc;
                    }
                    else
                    if (rootStrings[i].StartsWith("grModelMotion"))
                    {
                        var acc = new KAR_grModelMotion();
                        acc._s = str;
                        a      = acc;
                    }
                    else
                    if (rootStrings[i].StartsWith("grModel"))
                    {
                        var acc = new KAR_grModel();
                        acc._s = str;
                        a      = acc;
                    }
                    else
                    if (rootStrings[i].StartsWith("grData"))
                    {
                        var acc = new KAR_grData();
                        acc._s = str;
                        a      = acc;
                    }
                    else
                    if (rootStrings[i].EndsWith("_texg"))
                    {
                        var acc = new HSD_TEXGraphicBank();
                        acc._s = str;
                        a      = acc;
                    }
                    else
                    if (rootStrings[i].EndsWith("_ptcl"))
                    {
                        var acc = new HSD_ParticleGroup();
                        acc._s = str;
                        a      = acc;
                    }
                    else
                    if (rootStrings[i].StartsWith("eff"))
                    {
                        var acc = new SBM_EffectTable();
                        acc._s = str;
                        a      = acc;
                    }

                    Roots.Add(new HSDRootNode()
                    {
                        Name = rootStrings[i], Data = a
                    });
                }


                // set references
                for (int i = 0; i < refOffsets.Count; i++)
                {
                    HSDStruct   str = offsetToStruct[refOffsets[i]];
                    HSDAccessor a   = new HSDAccessor();
                    a._s = str;
                    References.Add(new HSDRootNode()
                    {
                        Name = refStrings[i], Data = a
                    });
                }
            }
        }