/// <summary>
        /// Pre-condition: stream's file position must be at the beginning of a new section, marked with 4/8 byte ascii strings
        /// </summary>
        /// <param name="stream"></param>
        /// <returns></returns>
        public static SaveSection ParseSaveSection(FileStream stream, SimCity2000Save save)
        {
            byte[] name = new byte[4];

            stream.Read(name, 0, 4);
            string sectionName = BytesToString(name);

            SaveSection newSection = null;

            switch (sectionName)
            {
                case "MISC":
                    newSection = new MiscSection();
                    break;
                case "ALTM":
                    newSection = new AltitudeSection();
                    break;
                case "XTER":
                    newSection = new TerrainSection();
                    break;
                case "XBLD":
                    newSection = new BuildingSection();
                    break;
                case "XZON":
                    newSection = new ZoneSection();
                    ((ZoneSection)newSection).MiscSection = save.MiscSection;
                    break;
                default:
                    newSection = new SaveSection(sectionName);
                    break;
            }

            newSection.ParseSection(stream);
            return newSection;
        }
 public TerrainGenerator(SimCity2000Save simCity, AnvilWorld world, BuildingSource buildingSource)
 {
     terrain = simCity.TerrainSection;
     altitude = simCity.AltitudeSection;
     buildings = simCity.BuildingSection;
     zones = simCity.ZoneSection;
     this.world = world;
     this.buildingSource = buildingSource;
     seaLevel = simCity.MiscSection.SeaLevel;
 }
        public static SimCity2000Save ParseSaveFile(string saveFilePath)
        {
            SimCity2000Save newSaveObject = new SimCity2000Save();

            FileStream reader = File.Open(saveFilePath, FileMode.Open, FileAccess.Read, FileShare.Read);

            if (reader.Length < 8)
            {
                throw new SimCityParseException("Unexpectedly short file length");
            }

            byte[] fileMagic = new byte[4];

            if (reader.Read(fileMagic, 0, 4) != 4)
            {
                throw new SimCityParseException("Not a valid Sim City save file");
            }

            // FORM
            if (fileMagic[0] != 0x46 || fileMagic[1] != 0x4f || fileMagic[2] != 0x52 || fileMagic[3] != 0x4d)
            {
                throw new SimCityParseException("Invalid magic file identifier bytes");
            }

            newSaveObject.length = reader.Read4ByteInt();

            // Read the Scdh header.
            byte[] scdhHeader = new byte[4];

            if (reader.Read(scdhHeader, 0, 4) != 4)
            {
                throw new SimCityParseException("Not a Sim City save file");
            }

            // SCDH
            if (scdhHeader[0] != 0x53 || scdhHeader[1] != 0x43 || scdhHeader[2] != 0x44 || scdhHeader[3] != 0x48)
            {
                throw new SimCityParseException("Not a Sim City save file");
            }

            // Read sections
            while (reader.Position < reader.Length)
            {
                newSaveObject.sections.Add(SectionFactory.ParseSaveSection(reader, newSaveObject));
            }

            reader.Close();

            newSaveObject.BuildingSection.SetZoneSection(newSaveObject.ZoneSection);
            newSaveObject.ZoneSection.MiscSection = newSaveObject.MiscSection;
            return newSaveObject;
        }
        public void DiffSections(SimCity2000Save oldSave)
        {
            foreach (SaveSection section in sections)
            {
                List<SectionDifference> diffs = section.Diff(oldSave.GetSection(section.Name));

                if (diffs.Count > 0)
                {
                    Console.WriteLine(section.Name);

                    foreach (SectionDifference diff in diffs)
                    {
                        Console.WriteLine(string.Format("{0}\t\t{1}\t\t{2}", diff.FieldName, diff.OldValue, diff.NewValue));
                    }
                }
            }
        }