Beispiel #1
0
 public override void Deserialise(Stream inStr)
 {
     Data = new byte[64];
     StreamUtils.EnsureRead(inStr, Data);
 }
Beispiel #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);
        }