コード例 #1
0
        //=========== READING ============
        #region Reading

        /** <summary> Returns an object info structure loaded from the specified stream. </summary> */
        public static ObjectDataInfo FromStream(Stream stream, bool readName)
        {
            ObjectDataInfo objInfo = new ObjectDataInfo();

            try {
                BinaryReader reader = new BinaryReader(stream, Encoding.Unicode);

                // Read the object data header
                objInfo.Flags    = reader.ReadUInt32();
                objInfo.FileName = "";
                for (int i = 0; i < 8; i++)
                {
                    char c = (char)reader.ReadByte();
                    if (c != ' ')
                    {
                        objInfo.FileName += c;
                    }
                }
                objInfo.CheckSum = reader.ReadUInt32();
                objInfo.Name     = "";

                if (readName)
                {
                    uint headerSize = 0x0;

                    switch (objInfo.Type)
                    {
                    case ObjectTypes.Attraction: headerSize = Attraction.HeaderSize; break;

                    case ObjectTypes.SmallScenery: headerSize = SmallScenery.HeaderSize; break;

                    case ObjectTypes.LargeScenery: headerSize = LargeScenery.HeaderSize; break;

                    case ObjectTypes.Wall: headerSize = Wall.HeaderSize; break;

                    case ObjectTypes.PathBanner: headerSize = PathBanner.HeaderSize; break;

                    case ObjectTypes.Path: headerSize = Pathing.HeaderSize; break;

                    case ObjectTypes.PathAddition: headerSize = PathAddition.HeaderSize; break;

                    case ObjectTypes.SceneryGroup: headerSize = SceneryGroup.HeaderSize; break;

                    case ObjectTypes.ParkEntrance: headerSize = ParkEntrance.HeaderSize; break;

                    case ObjectTypes.Water: headerSize = Water.HeaderSize; break;

                    case ObjectTypes.ScenarioText: headerSize = ScenarioText.HeaderSize; break;

                    default: objInfo.Flags = 0xFFFFFFFF; break;
                    }

                    // Decode enough of the chunk to get the name
                    if (headerSize != 0x0)
                    {
                        ReadChunkInfo(reader, objInfo.Type, headerSize, ref objInfo);
                    }
                }
                reader.Close();
            }
            catch (System.Exception) {
                objInfo.Flags = 0xFFFFFFFF;
            }

            return(objInfo);
        }
コード例 #2
0
        /** <summary> Reads and decodes the chunk. </summary> */
        internal static void ReadChunkInfo(BinaryReader reader, ObjectTypes type, uint headerSize, ref ObjectDataInfo objInfo)
        {
            ChunkEncoding encoding      = (ChunkEncoding)reader.ReadByte();
            uint          chunkSize     = reader.ReadUInt32();
            uint          chunkPosition = 0;
            uint          position      = 0;
            long          startPos      = reader.BaseStream.Position;

            MemoryStream stream = new MemoryStream();
            BinaryWriter writer = new BinaryWriter(stream);

            switch (encoding)
            {
            case ChunkEncoding.None:

                //Console.WriteLine("None");
                writer.Write(reader.ReadBytes((int)headerSize + 200));
                position += headerSize + 200;

                break;

            case ChunkEncoding.RLE:
            case ChunkEncoding.RLEString:

                //Console.WriteLine((encoding == EncodingType.RLE ? "RLE" : "RLEString"));
                //http://tid.rctspace.com/RLE.html

                // While the end of the uncompressed chunk has not been reached
                while (chunkPosition < (long)chunkSize && position < headerSize + 200)
                {
                    // Read the next byte
                    byte b = reader.ReadByte();

                    // If the MSB is 0, copy the next (b + 1) bytes
                    if ((b & 0x80) == 0)
                    {
                        uint length = (uint)(b + 1);
                        chunkPosition += length + 1;
                        position      += length;
                        //Console.WriteLine("Copy: " + b + " " + length + " Position: " + chunkPosition);
                        writer.Write(reader.ReadBytes((int)length));
                    }

                    // Else the MSB is 1, repeat the following byte (-b + 1) times
                    else
                    {
                        byte copyByte = reader.ReadByte();
                        uint length   = (uint)((byte)(-(sbyte)b) + 1);
                        chunkPosition += 2;
                        position      += length;
                        //Console.WriteLine("Repeat: " + b + " " + length + " " + copyByte + " Position: " + chunkPosition);
                        for (var i = 0; i < length; i++)
                        {
                            writer.Write(copyByte);
                        }
                    }
                }

                // Decompress strings
                if (encoding == ChunkEncoding.RLEString)
                {
                    Console.WriteLine("RLE String Encoding not supported!");
                }

                break;

            case ChunkEncoding.Rotate:
                int shift = 1;
                while (chunkPosition < (long)chunkSize)
                {
                    byte b = reader.ReadByte();
                    b = (byte)((b >> shift) | (b << (8 - shift)));
                    writer.Write(b);
                    chunkPosition++;
                    position++;
                    shift = (shift + 2) % 8;
                }
                break;
            }

            writer.Close();
            BinaryReader reader2 = new BinaryReader(new MemoryStream(stream.GetBuffer()));

            switch (type)
            {
            case ObjectTypes.Attraction: objInfo.Header = new AttractionHeader(); break;

            case ObjectTypes.SmallScenery: objInfo.Header = new SmallSceneryHeader(); break;

            case ObjectTypes.LargeScenery: objInfo.Header = new LargeSceneryHeader(); break;

            case ObjectTypes.Wall: objInfo.Header = new WallHeader(); break;

            case ObjectTypes.PathBanner: objInfo.Header = new PathBannerHeader(); break;

            case ObjectTypes.Path: objInfo.Header = new PathingHeader(); break;

            case ObjectTypes.PathAddition: objInfo.Header = new PathAdditionHeader(); break;

            case ObjectTypes.SceneryGroup: objInfo.Header = new SceneryGroupHeader(); break;

            case ObjectTypes.ParkEntrance: objInfo.Header = new ParkEntranceHeader(); break;

            case ObjectTypes.Water: objInfo.Header = new WaterHeader(); break;

            case ObjectTypes.ScenarioText: objInfo.Header = new ScenarioTextHeader(); break;
            }
            if (objInfo.Header != null)
            {
                objInfo.Header.Read(reader2);
                objInfo.Subtype = objInfo.Header.ObjectSubtype;
            }
            else
            {
                reader2.ReadBytes((int)headerSize);
            }

            byte bs = reader2.ReadByte();

            objInfo.Name = "";
            // If the lanuage index is 0xFF, end the string table
            while (bs != 0xFF && bs < 2 && objInfo.Name.Replace(" ", "").Length == 0)
            {
                // Read the null-terminated string
                objInfo.Name = "";
                char c = (char)reader2.ReadByte();
                while (c != 0x00)
                {
                    objInfo.Name += c;
                    c             = (char)reader2.ReadByte();
                }
                bs = reader2.ReadByte();
            }

            reader2.Close();
            stream.Close();
        }