Beispiel #1
0
        /// <summary>
        /// Initializes a new instance of the <see cref="DAT"/> class.
        /// </summary>
        /// <param name="s">The s.</param>
        public DAT(Stream s)
        {
            Chunks.Clear();
            ByteCover.Clear();
            ByteCoverName.Clear();
            AllVertices.Clear();
            AllNormals.Clear();
            AllTriangles.Clear();
            vismapid.Clear();
            br = new BinaryReader(s);
            while (s.Position < s.Length)
            {
                long  offset = s.Position;
                CHUNK c      = new CHUNK(s);
                uint  d1     = (c.data.Length >= 4) ? BitConverter.ToUInt32(c.data, 0) : 0;
                uint  d2     = (c.data.Length >= 8) ? BitConverter.ToUInt32(c.data, 4) : 0;
                ////Console.WriteLine("chunk: {0,8:x8} : {1}:{2,2:x2} {3,8:x8} bytes / {4,8:x8} {5,8:x8}", offset, c.FourCC, c.Type, c.Length, d1, d2);

                //File.WriteAllBytes(string.Format("{0,4:x4}{1}.enc", Chunks.Count, c.FourCC), c.data);
                CHUNK.Decrypt(c.data);
                string filename = string.Format("{0,4:x4}-{1}-{2,2:x2}.dec", Chunks.Count, c.FourCC, c.Type);
#if WRITE_CHUNKS_TO_DISK
                if (!File.Exists(filename))
                {
                    File.WriteAllBytes(filename, c.data);
                }
#endif
                c.Number = Chunks.Count;

                Chunks.Add(c);
            }
            s.Dispose();
            br.Close();
            br.Dispose();
        }
Beispiel #2
0
        /// <summary>
        /// Parse2s the e.
        /// </summary>
        /// <param name="c">The c.</param>
        public void Parse2E(CHUNK c)
        {
            int hcount = c.data[0x20];

            //if (maxcount != 0 && maxcount != 1) //Console.WriteLine("{0,4:x4}", c.Number);
            if (hcount == 0)
            {
                return;              // whatever
            }
            //if (c.data[0x60] != 'm') //Console.WriteLine("{0,4:x4}", c.Number);
            // type at [0x60..0x67] is "warp    " or "model   " or "        "

            int numpoints = BitConverter.ToInt32(c.data, 0x70);

            for (int i = 0; i < numpoints; i++)
            {
            }
        }
Beispiel #3
0
        /// <summary>
        /// Parse20s the specified c.
        /// </summary>
        /// <param name="c">The c.</param>
        public void Parse20(CHUNK c)
        {
            //Debugger.Break();
            var filename    = string.Format("{0,4:x4}-{1}-{2,2:x2}.dec", c.Number, c.FourCC, c.Type);
            var filenamepng = string.Format("{0,4:x4}-{1}-{2,2:x2}.png", c.Number, c.FourCC, c.Type);

#if false
            var psi = new ProcessStartInfo("dxt3.exe", "\"" + filename + "\"");
            var p   = Process.Start(psi);
            p.WaitForExit();
            if (!Directory.Exists("out"))
            {
                Directory.CreateDirectory("out");
            }
            if (File.Exists("out.png"))
            {
                File.Move("out.png", Path.Combine("out", filenamepng));
            }
#endif
        }
Beispiel #4
0
        /// <summary>
        /// Parse1s the c.
        /// </summary>
        /// <param name="c">The c.</param>
        public void Parse1C(CHUNK c)
        {
            // map

            int meshoffset       = BitConverter.ToInt32(c.data, 8); // stores info about the collision mesh
            int gridwidth        = 20 * c.data[0x0c];               // stored div 10
            int gridheight       = 20 * c.data[0x0d];
            int bucketwidth      = c.data[0x0e];                    // almost always 40?
            int bucketheight     = c.data[0x0f];                    // stored mul 10; so 40 = 4 yalms; probably baked in so gridwidth*bucketwidth = mapwidth
            int quadtreeoffset   = BitConverter.ToInt32(c.data, 0x10);
            int objectsoffset    = 0x20;
            int objectsendoffset = BitConverter.ToInt32(c.data, 0x14);
            int objectscount     = (objectsendoffset - objectsoffset) / 0x64;
            int shortnameoffset  = BitConverter.ToInt32(c.data, 0x18);
            int shortnamescount  = (meshoffset - shortnameoffset) / 0x4c;

            AddByteCover("header", 0, 0x20);

            // collision mesh
            // - use the grid for fast location-based queries, or
            // - use the list directly if you want to enumerate all the meshes (grid is also fine
            // for this, just skip over the null pointers)
            // - dont use the mesh data directly because it stores grid-local coordinates and also
            // lacks transformations
            int meshmodelcount           = BitConverter.ToInt32(c.data, meshoffset + 0x00);
            int meshmodeldata            = BitConverter.ToInt32(c.data, meshoffset + 0x04);     // raw mesh data, don't use this, it is local object data and doesn't have transformations applied
            int meshgridbucketlistscount = BitConverter.ToInt32(c.data, meshoffset + 0x08);
            int meshgridbucketlists      = BitConverter.ToInt32(c.data, meshoffset + 0x0c);     // each bucket has a list of {meshdata,transformation} and the list is zero terminated
            int gridoffset = BitConverter.ToInt32(c.data, meshoffset + 0x10);                   // whole map is divided into a grid; each bucket points to its list entry

            ////Console.WriteLine("mesh: {0} {1} {2} {3} {4}", meshmodelcount.ToString("x8"), meshmodeldata.ToString("x8"), meshgridbucketlistscount.ToString("x8"), meshgridbucketlists.ToString("x8"), gridoffset.ToString("x8"));

            int mapidlistoffset = BitConverter.ToInt32(c.data, meshoffset + 0x14);
            int mapidlistcount  = BitConverter.ToInt32(c.data, meshoffset + 0x18);

            AddByteCover("meshheader", meshoffset, 0x20);

            //Console.WriteLine("meshes:");
            int j = meshmodeldata;

            Console.WriteLine(j);
            for (int i = 0; i < meshmodelcount; i++)
            {
                ////Console.Write("{0,4:x4} |", i);
                int retj = ParseMesh(c.data, j);
                AddByteCover("meshes", j, retj - j);
                j = retj;
            }

            // this loop populates global AllVertices AllNormals AllTriangles (sorry for statics; if you plan on using this for more than one map at a time, rewrite to be less staticy)
            //Console.WriteLine("grid:");
            try
            {
                int offs      = 0;
                int entryoffs = 0;
                for (int y = 0; y < gridheight; y++)
                {
                    for (int x = 0; x < gridwidth; x++)
                    {
                        offs      = (y * gridwidth + x) * 4;
                        entryoffs = BitConverter.ToInt32(c.data, gridoffset + offs);
                        if (entryoffs != 0 && entryoffs ! < 0)
                        {
                            ParseGridEntry(c.data, entryoffs, x, y);
                        }
                        AddByteCover("grid", gridoffset + offs, 4);
                    }
                }
            }
            catch (Exception ex)
            {
                Char.Logger.AddDebugText(Char.Tc.rtbDebug, ex.ToString());
            }
#if WRITE_COLLISION_MESH_TO_DISK
            // write out the collision mesh in some format
            using (var sw = new StreamWriter(string.Format(@"Map Collision obj\{0}.obj", FileName)))
            {
                foreach (var v in AllVertices)
                {
                    sw.WriteLine("v {0} {1} {2}", v.x, v.y, -v.z);
                }
                foreach (var n in AllNormals)
                {
                    sw.WriteLine("vn {0} {1} {2}", n.nx, n.ny, -n.nz);
                }

                foreach (var t in AllTriangles)
                {
                    sw.WriteLine("f {0}//{1} {2}//{3} {4}//{5}",
                                 1 + t.iv0, 1 + t.in0,
                                 1 + t.iv1, 1 + t.in0,
                                 1 + t.iv2, 1 + t.in0
                                 );
                }
            }
#endif

            //Console.WriteLine("shortnames:");
            for (int i = 0; i < shortnamescount; i++)
            {
                string name = Encoding.ASCII.GetString(c.data, shortnameoffset + i * 0x4c, 0x20);
                ////Console.Write("{0,4:x4} | {1}", i, name);
                AddByteCover("shortnames", shortnameoffset + i * 0x4c, 0x4c);
            }
            //Console.WriteLine();

            //Console.WriteLine("objects:");
            for (int i = 0; i < objectscount; i++)
            {
                //Console.Write("{0,4:x4} |", i);
                ParseObject(c.data, objectsoffset + i * 0x64);
                AddByteCover("objects", objectsoffset + i * 0x64, 0x64);
            }

            //Console.WriteLine("vislist:");
            for (int i = 0; i < mapidlistcount; i++)
            {
                //Console.Write("{0,4:x4} |", i);
                int mapid = ParseMapIDStruct(c.data, mapidlistoffset + 0xc0 * i);
                vismapid.Add(i, mapid);
                AddByteCover("vislist", mapidlistoffset + 0xc0 * i, 0xc0);
            }

            // quadtree does multiple things:
            // - given a position, traverse down to some bucket
            // - each bucket tells you what things are visible, which improves speed of game by limiting objects/polygons drawn
            // - also tells you the 2D sub map id for a given 3D point (to pull up the proper 2D image when you open up /map)
            // quadtree volumes have some transformations that I haven't bothered to apply
            // quadtree stores entire vertical column (i.e. it is not really an octree)
            //Console.WriteLine("quadtree:");
            BBT root = ParseQuadTree(c.data, quadtreeoffset, 1);

#if false
            // query position to mapid(s)
            BBT found = root.find(-30, 0, 380);
            foreach (int node in found.matchids)
            {
                Console.WriteLine("{0}", node);
            }
            foreach (int mapid in found.matches)
            {
                Console.WriteLine("{0}", mapid);
            }
#endif

            AddByteCover("EOF", c.data.Length, 1);

            PrintByteCover();
        }
Beispiel #5
0
        /// <summary>
        /// Parse36s the specified c.
        /// </summary>
        /// <param name="c">The c.</param>
        public void Parse36(CHUNK c)
        {
            // if .zoneid same as current zone, region is probably a "zone line"
            // - if srcordst is 0, the volume zones out
            // - if srcordst is 1, the volume is the random region where you zone in (but your
            // rotation will come from zone out)

            var l = new Subregion();

            int count = BitConverter.ToInt32(c.data, 0x30);

            for (int i = 0; i < count; i++)
            {
                var o = new Subregion();

                o.x  = BitConverter.ToSingle(c.data, 0x40 + i * 0x40 + 0x00);
                o.y  = BitConverter.ToSingle(c.data, 0x40 + i * 0x40 + 0x04);
                o.z  = BitConverter.ToSingle(c.data, 0x40 + i * 0x40 + 0x08);
                o.rx = BitConverter.ToSingle(c.data, 0x40 + i * 0x40 + 0x0c);
                o.ry = BitConverter.ToSingle(c.data, 0x40 + i * 0x40 + 0x10);
                o.rz = BitConverter.ToSingle(c.data, 0x40 + i * 0x40 + 0x14);
                o.vx = BitConverter.ToSingle(c.data, 0x40 + i * 0x40 + 0x18);
                o.vy = BitConverter.ToSingle(c.data, 0x40 + i * 0x40 + 0x1c);
                o.vz = BitConverter.ToSingle(c.data, 0x40 + i * 0x40 + 0x20);

                byte[] namebytes = new byte[8];
                Array.Copy(c.data, 0x40 + i * 0x40 + 0x24, namebytes, 0, 8);
                int len = 0;
                while (len < namebytes.Length && namebytes[len] != 0)
                {
                    len++;
                }
                len    = 8;
                o.name = Encoding.ASCII.GetString(namebytes, 0, len);

                o.zoneid   = BitConverter.ToInt32(c.data, 0x40 + i * 0x40 + 0x2c);
                o.srcordst = BitConverter.ToInt32(c.data, 0x40 + i * 0x40 + 0x30);

#if true
                /*Console.WriteLine("{0,8} {1} {2} : {3,8},{4,8},{5,8} : {6,8},{7,8},{8,8} : {9,8},{10,8},{11,8}",
                 *  o.name, o.srcordst, o.zoneid.ToString("x4"),
                 *  o.x.ToString("N2"), o.y.ToString("N2"), o.z.ToString("N2"),
                 *  o.rx.ToString("N2"), o.ry.ToString("N2"), o.rz.ToString("N2"),
                 *  o.vx.ToString("N2"), o.vy.ToString("N2"), o.vz.ToString("N2")
                 * );*/
#endif

                if (true || o.srcordst == 0)
                {
                    float vx = o.vx / 2;
                    float vy = o.vy / 2;
                    float vz = o.vz / 2;
                    float ry = -o.ry;

                    //Console.WriteLine("{0} {1} {2} {3} {4} {5} 0.5", o.x + rotx(-vx, vz, ry), o.z + roty(-vx, vz, ry), o.y, o.x + rotx(vx, vz, ry), o.z + roty(vx, vz, ry), o.y);
                    //Console.WriteLine("{0} {1} {2} {3} {4} {5} 0.5", o.x + rotx(vx, vz, ry), o.z + roty(vx, vz, ry), o.y, o.x + rotx(vx, -vz, ry), o.z + roty(vx, -vz, ry), o.y);
                    //Console.WriteLine("{0} {1} {2} {3} {4} {5} 0.5", o.x + rotx(vx, -vz, ry), o.z + roty(vx, -vz, ry), o.y, o.x + rotx(-vx, -vz, ry), o.z + roty(-vx, -vz, ry), o.y);
                    //Console.WriteLine("{0} {1} {2} {3} {4} {5} 0.5", o.x + rotx(-vx, -vz, ry), o.z + roty(-vx, -vz, ry), o.y, o.x + rotx(-vx, vz, ry), o.z + roty(-vx, vz, ry), o.y);

                    ////Console.WriteLine("{0} {1} {2} {3} {4} {5} 0.5", o.x + rotx(-vx, -vz, ry), o.z + roty(-vx, -vz, ry), o.y, o.x + rotx(vx, vz, ry), o.z + roty(vx, vz, ry), o.y);
                    ////Console.WriteLine("{0} {1} {2} {3} {4} {5} 0.5", o.x + rotx(vx, -vz, ry), o.z + roty(vx, -vz, ry), o.y, o.x + rotx(-vx, -vz, ry), o.z + roty(-vx, -vz, ry), o.y);
                }

                l = o;
            }
        }