Пример #1
0
 public override void ReplaceChild(Chunk xiFrom, Chunk xiTo)
 {
     if (xiFrom == NamedImageGroups)
     {
         NamedImageGroups = (GroupingChunk)xiTo;
     }
     else if (xiFrom == OBJTFalseStart)
     {
         OBJTFalseStart = (RawDataChunk)xiTo;
     }
     else if (xiFrom == OBJT)
     {
         OBJT = (OBJTChunk)xiTo;
     }
     else if (xiFrom == Dunno)
     {
         Dunno = (RawDataChunk)xiTo;
     }
     else if (xiFrom == SHET)
     {
         SHET = (SHETChunk)xiTo;
     }
     else
     {
         throw new ArgumentException("xifrom not found!");
     }
 }
Пример #2
0
        public override void Deserialise(Stream inStr)
        {
            if (inStr is FileStream)
              {
            mName = ((FileStream)inStr).Name;
              }

              //BinaryReader is little-endian
              BinaryReader bin = new BinaryReader(inStr);

              //first, a header of 4 int32s:
              Header = new int[4];
              for (int i = 0; i < Header.Length; i++)
            Header[i] = bin.ReadInt32();

              //then, a block of zero bytes (int32 aligned)
              int nextInt = bin.ReadInt32();
              ZeroByteCount = 0;
              while (nextInt == 0)
              {
            ZeroByteCount += 4;
            nextInt = bin.ReadInt32();
              }

              ArrayList imageGroups = new ArrayList();

              //now, an array of image or comment structs
              int lTIMIdx = 0;
              while (nextInt != 0)
              {
            bin.BaseStream.Seek(-4, SeekOrigin.Current);
            NamedImageGroup nim = new NamedImageGroup(bin.BaseStream, ref lTIMIdx);
            imageGroups.Add(nim);
            nextInt = bin.ReadInt32();
              }

              //nextInt is len == 0.
              //There will be one more zero int32, then OBJTs
              nextInt = bin.ReadInt32();
              if (nextInt != 0)
            throw new DeserialisationException(string.Format("Expecting int32 0, found {0} at offset {1}", nextInt, inStr.Position - 4));

              //make a child to hold the EOF marker
              imageGroups.Add(new RawDataChunk("EOF marker", new byte[8]));

              //put the children so far in a grouping chunk
              NamedImageGroups = new GroupingChunk("textures and sprites", (Chunk[])imageGroups.ToArray(typeof(Chunk)));

              //Now the objects:
              //because of a bizzarre quirk here, the object chunk starts, then stops, then starts again
              long lObjtFalseStartPos = inStr.Position;

              try
              {
            OBJTChunk lFalseObjt = new OBJTChunk();
            lFalseObjt.Deserialise(inStr);
            OBJT = lFalseObjt;
              }
              catch (DeserialisationException e)
              {
            //Console.Error.WriteLine("OBJT false start found, searching for restart...");

            //look for X,0,65,0 in first bit:
            inStr.Seek(lObjtFalseStartPos, SeekOrigin.Begin);
            int lX = bin.ReadInt32();
            if (bin.ReadInt32() != 0) throw new DeserialisationException("Expecting 0", inStr.Position);
            if (bin.ReadInt32() != 65) throw new DeserialisationException("Expecting 65", inStr.Position);
            if (bin.ReadInt32() != 0) throw new DeserialisationException("Expecting 0", inStr.Position);

            if (lX == 65) throw new Exception("I haven't planned for this case!");

            int[] lMatcher = new int[] { 0, 65, 0 };

            //longest observed false starts are Pool3 (1052 bytes) and Rest4 (2032 bytes)
            while (inStr.Position - lObjtFalseStartPos < 2100)
            {
              int lNext = bin.ReadInt32();
              if (lNext == lX)
              {
            if (Utils.ArrayCompare(lMatcher, new int[] { bin.ReadInt32(), bin.ReadInt32(), bin.ReadInt32() }))
            {
              int lFalseStartLen = (int)(inStr.Position - 4 * 4 - lObjtFalseStartPos);
              inStr.Seek(lObjtFalseStartPos, SeekOrigin.Begin);
              OBJTFalseStart = new RawDataChunk("OBJT False Start", bin.ReadBytes(lFalseStartLen));
              OBJT = new OBJTChunk();
              OBJT.Deserialise(inStr);
              break;
            }
              }
            }
            if (OBJT == null)
            {
              string lFileName = inStr is FileStream ? ((FileStream)inStr).Name : "unknown";
              System.Windows.Forms.MessageBox.Show(string.Format("Warning: OBJTs not loaded on level {0}: unable to find false start resumption after: {1}", lFileName, e));
              inStr.Seek(lObjtFalseStartPos, SeekOrigin.Begin);
            }
              }

              //read the rest of the file into a "remainder"
              //byte array so we can search for the SHET
              long lStartOfObjts = inStr.Position;
              byte[] lRest = new byte[inStr.Length - lStartOfObjts];

              StreamUtils.EnsureRead(inStr, lRest);

              //use a heuristic to find the SHET.
              //
              //we need an 8bit char set (ASCII is 7bit). windows-1252 will do
              string lRestAsString = Encoding.GetEncoding("windows-1252").GetString(lRest);
              Regex lSHETStartRegex = new Regex(
              "([a-zA-Z0-9'()*+.\\-_ ]{10,13})\0([a-zA-Z0-9'()*+.\\-_ ]{10,13})\0(.{7})",
              RegexOptions.CultureInvariant | RegexOptions.Singleline);

              MatchCollection matches = lSHETStartRegex.Matches(lRestAsString);
              if (matches.Count != 1)
            throw new DeserialisationException(string.Format("Expecting exactly one match for SHET start regex. Found {0}", matches.Count));

              int SHETstart = matches[0].Index; //(relative to end of images section)

              byte[] dunno = new byte[SHETstart];
              Array.Copy(lRest, 0, dunno, 0, SHETstart);
              Dunno = new RawDataChunk("Dunno", dunno);

              //seek to the start of the SHET, and pretend we got here without cheating!
              dunno = lRest = null;
              inStr.Seek(lStartOfObjts + SHETstart, SeekOrigin.Begin);

              SHET = new SHETChunk(inStr, bin);
        }
Пример #3
0
 public override void ReplaceChild(Chunk xiFrom, Chunk xiTo)
 {
     if (xiFrom == NamedImageGroups)
       {
     NamedImageGroups = (GroupingChunk)xiTo;
       }
       else if (xiFrom == OBJTFalseStart)
       {
     OBJTFalseStart = (RawDataChunk)xiTo;
       }
       else if (xiFrom == OBJT)
       {
     OBJT = (OBJTChunk)xiTo;
       }
       else if (xiFrom == Dunno)
       {
     Dunno = (RawDataChunk)xiTo;
       }
       else if (xiFrom == SHET)
       {
     SHET = (SHETChunk)xiTo;
       }
       else
       {
       throw new ArgumentException("xifrom not found!");
       }
 }
Пример #4
0
        public override void Deserialise(Stream inStr)
        {
            if (inStr is FileStream)
            {
                mName = ((FileStream)inStr).Name;
            }

            //BinaryReader is little-endian
            BinaryReader bin = new BinaryReader(inStr);

            //first, a header of 4 int32s:
            Header = new int[4];
            for (int i = 0; i < Header.Length; i++)
            {
                Header[i] = bin.ReadInt32();
            }

            //then, a block of zero bytes (int32 aligned)
            int nextInt = bin.ReadInt32();

            ZeroByteCount = 0;
            while (nextInt == 0)
            {
                ZeroByteCount += 4;
                nextInt        = bin.ReadInt32();
            }

            ArrayList imageGroups = new ArrayList();

            //now, an array of image or comment structs
            int lTIMIdx = 0;

            while (nextInt != 0)
            {
                bin.BaseStream.Seek(-4, SeekOrigin.Current);
                NamedImageGroup nim = new NamedImageGroup(bin.BaseStream, ref lTIMIdx);
                imageGroups.Add(nim);
                nextInt = bin.ReadInt32();
            }

            //nextInt is len == 0.
            //There will be one more zero int32, then OBJTs
            nextInt = bin.ReadInt32();
            if (nextInt != 0)
            {
                throw new DeserialisationException(string.Format("Expecting int32 0, found {0} at offset {1}", nextInt, inStr.Position - 4));
            }

            //make a child to hold the EOF marker
            imageGroups.Add(new RawDataChunk("EOF marker", new byte[8]));

            //put the children so far in a grouping chunk
            NamedImageGroups = new GroupingChunk("textures and sprites", (Chunk[])imageGroups.ToArray(typeof(Chunk)));

            //Now the objects:
            //because of a bizzarre quirk here, the object chunk starts, then stops, then starts again
            long lObjtFalseStartPos = inStr.Position;

            try
            {
                OBJTChunk lFalseObjt = new OBJTChunk();
                lFalseObjt.Deserialise(inStr);
                OBJT = lFalseObjt;
            }
            catch (DeserialisationException e)
            {
                //Console.Error.WriteLine("OBJT false start found, searching for restart...");

                //look for X,0,65,0 in first bit:
                inStr.Seek(lObjtFalseStartPos, SeekOrigin.Begin);
                int lX = bin.ReadInt32();
                if (bin.ReadInt32() != 0)
                {
                    throw new DeserialisationException("Expecting 0", inStr.Position);
                }
                if (bin.ReadInt32() != 65)
                {
                    throw new DeserialisationException("Expecting 65", inStr.Position);
                }
                if (bin.ReadInt32() != 0)
                {
                    throw new DeserialisationException("Expecting 0", inStr.Position);
                }

                if (lX == 65)
                {
                    throw new Exception("I haven't planned for this case!");
                }

                int[] lMatcher = new int[] { 0, 65, 0 };

                //longest observed false starts are Pool3 (1052 bytes) and Rest4 (2032 bytes)
                while (inStr.Position - lObjtFalseStartPos < 2100)
                {
                    int lNext = bin.ReadInt32();
                    if (lNext == lX)
                    {
                        if (Utils.ArrayCompare(lMatcher, new int[] { bin.ReadInt32(), bin.ReadInt32(), bin.ReadInt32() }))
                        {
                            int lFalseStartLen = (int)(inStr.Position - 4 * 4 - lObjtFalseStartPos);
                            inStr.Seek(lObjtFalseStartPos, SeekOrigin.Begin);
                            OBJTFalseStart = new RawDataChunk("OBJT False Start", bin.ReadBytes(lFalseStartLen));
                            OBJT           = new OBJTChunk();
                            OBJT.Deserialise(inStr);
                            break;
                        }
                    }
                }
                if (OBJT == null)
                {
                    string lFileName = inStr is FileStream ? ((FileStream)inStr).Name : "unknown";
                    System.Windows.Forms.MessageBox.Show(string.Format("Warning: OBJTs not loaded on level {0}: unable to find false start resumption after: {1}", lFileName, e));
                    inStr.Seek(lObjtFalseStartPos, SeekOrigin.Begin);
                }
            }

            //read the rest of the file into a "remainder"
            //byte array so we can search for the SHET
            long lStartOfObjts = inStr.Position;

            byte[] lRest = new byte[inStr.Length - lStartOfObjts];

            StreamUtils.EnsureRead(inStr, lRest);

            //use a heuristic to find the SHET.
            //
            //we need an 8bit char set (ASCII is 7bit). windows-1252 will do
            string lRestAsString   = Encoding.GetEncoding("windows-1252").GetString(lRest);
            Regex  lSHETStartRegex = new Regex(
                "([a-zA-Z0-9'()*+.\\-_ ]{10,13})\0([a-zA-Z0-9'()*+.\\-_ ]{10,13})\0(.{7})",
                RegexOptions.CultureInvariant | RegexOptions.Singleline);

            MatchCollection matches = lSHETStartRegex.Matches(lRestAsString);

            if (matches.Count != 1)
            {
                throw new DeserialisationException(string.Format("Expecting exactly one match for SHET start regex. Found {0}", matches.Count));
            }

            int SHETstart = matches[0].Index; //(relative to end of images section)

            byte[] dunno = new byte[SHETstart];
            Array.Copy(lRest, 0, dunno, 0, SHETstart);
            Dunno = new RawDataChunk("Dunno", dunno);

            //seek to the start of the SHET, and pretend we got here without cheating!
            dunno = lRest = null;
            inStr.Seek(lStartOfObjts + SHETstart, SeekOrigin.Begin);

            SHET = new SHETChunk(inStr, bin);
        }