コード例 #1
0
ファイル: Messages.cs プロジェクト: Metibor/Ambermoon
        /// <summary>
        /// The position of the data reader should be at
        /// the start of the message sections just behind the
        /// insert disk messages.
        ///
        /// It will be behind all the message sections after this.
        /// </summary>
        internal Messages(IDataReader dataReader)
        {
            while (Entries.Count < NumFirstMessages)
            {
                ReadText(dataReader);
            }

            --dataReader.Position;
            dataReader.AlignToWord();

            int numIndices = (int)dataReader.ReadDword();

            UnknownIndices = new List <uint>(numIndices);

            for (int i = 0; i < numIndices; ++i)
            {
                UnknownIndices.Add(dataReader.ReadWord());
            }

            while (Entries.Count < NumFirstMessages + NumSecondMessages)
            {
                ReadText(dataReader);
            }

            dataReader.AlignToWord();
        }
コード例 #2
0
        // Second data hunk, right behind UITexts.
        internal Buttons(IDataReader dataReader)
        {
            var graphicInfo = new GraphicInfo
            {
                Width         = 32,
                Height        = 13,
                Alpha         = true,
                GraphicFormat = GraphicFormat.Palette3Bit,
                PaletteOffset = 24
            };
            var graphicReader = new GraphicReader();

            Graphic ReadGraphic(IDataReader dataReader)
            {
                var graphic = new Graphic();

                graphicReader.ReadGraphic(graphic, dataReader, graphicInfo);

                return(graphic);
            }

            foreach (var buttonType in Enum.GetValues <ButtonType>())
            {
                entries.Add(buttonType, ReadGraphic(dataReader));
            }

            dataReader.AlignToWord();
        }
コード例 #3
0
ファイル: Messages.cs プロジェクト: Pyrdacor/Ambermoon.net
        /// <summary>
        /// The position of the data reader should be at
        /// the start of the message sections just behind the
        /// insert disk messages.
        ///
        /// It will be behind all the message sections after this.
        /// </summary>
        internal Messages(IDataReader dataReader)
        {
            while (ReadText(dataReader))
            {
                ;
            }

            int numTextEntries   = (int)dataReader.ReadDword();
            var textEntryLengths = new List <uint>(numTextEntries);

            for (int i = 0; i < numTextEntries; ++i)
            {
                textEntryLengths.Add(dataReader.ReadWord());
            }

            for (int i = 0; i < numTextEntries; ++i)
            {
                entries.Add(dataReader.ReadString((int)textEntryLengths[i], AmigaExecutable.Encoding).TrimEnd('\0'));
            }

            dataReader.AlignToWord();

            if (dataReader.PeekWord() == 0)
            {
                dataReader.Position += 2;
            }
        }
コード例 #4
0
ファイル: AutomapNames.cs プロジェクト: Metibor/Ambermoon
        /// <summary>
        /// The position of the data reader should be at
        /// the start of the automap names just behind the
        /// messages.
        ///
        /// It will be behind the automap names after this.
        /// </summary>
        internal AutomapNames(IDataReader dataReader)
        {
            foreach (var type in Enum.GetValues(typeof(AutomapType)))
            {
                Entries.Add((AutomapType)type, dataReader.ReadNullTerminatedString());
            }

            dataReader.AlignToWord();
        }
コード例 #5
0
ファイル: SongNames.cs プロジェクト: Metibor/Ambermoon
        /// <summary>
        /// The position of the data reader should be at
        /// the start of the song names just behind the
        /// option names.
        ///
        /// It will be behind the song names after this.
        /// </summary>
        internal SongNames(IDataReader dataReader)
        {
            for (int i = 0; i < NumSongs; ++i)
            {
                Entries.Add(dataReader.ReadNullTerminatedString());
            }

            dataReader.AlignToWord();
        }
コード例 #6
0
ファイル: OptionNames.cs プロジェクト: Metibor/Ambermoon
        /// <summary>
        /// The position of the data reader should be at
        /// the start of the option names just behind the
        /// automap names.
        ///
        /// It will be behind the option names after this.
        /// </summary>
        internal OptionNames(IDataReader dataReader)
        {
            foreach (Option type in Enum.GetValues(typeof(Option)))
            {
                Entries.Add(type, dataReader.ReadNullTerminatedString());
            }

            dataReader.AlignToWord();
        }
コード例 #7
0
        /// <summary>
        /// The position of the data reader should be at
        /// the start of the automap names just behind the
        /// messages.
        ///
        /// It will be behind the automap names after this.
        /// </summary>
        internal AutomapNames(IDataReader dataReader)
        {
            entries.Add(AutomapType.None, "");
            entries.Add(AutomapType.Wall, "");

            foreach (var type in Enum.GetValues <AutomapType>().Skip(2).Take(17))
            {
                entries.Add(type, dataReader.ReadNullTerminatedString(AmigaExecutable.Encoding));
            }

            dataReader.AlignToWord();
        }
コード例 #8
0
ファイル: Messages.cs プロジェクト: Metibor/Ambermoon
        void ReadText(IDataReader dataReader)
        {
            if (dataReader.PeekWord() == 0) // offset section / split text with placeholders
            {
                dataReader.AlignToWord();

                if (dataReader.PeekWord() != 0)
                {
                    throw new AmbermoonException(ExceptionScope.Data, "Invalid text section.");
                }

                while (dataReader.PeekDword() == 0)
                {
                    dataReader.Position += 4;
                }

                string text      = "";
                var    offsets   = new List <uint>();
                int    endOffset = dataReader.Position;

                while (dataReader.PeekByte() == 0)
                {
                    offsets.Add(dataReader.ReadDword());
                    dataReader.ReadDword(); // TODO: always 0? Maybe some placeholder index reshifting?
                }

                for (int i = 0; i < offsets.Count; ++i)
                {
                    dataReader.Position = (int)offsets[i];
                    text += dataReader.ReadNullTerminatedString();

                    if (i != offsets.Count - 1) // Insert placeholder
                    {
                        text += "{" + i + "}";
                    }

                    if (dataReader.Position > endOffset)
                    {
                        endOffset = dataReader.Position;
                    }
                }

                Entries.Add(text);
                dataReader.Position = endOffset;
            }
            else // just a text
            {
                Entries.Add(dataReader.ReadNullTerminatedString());
            }
        }
コード例 #9
0
ファイル: OptionNames.cs プロジェクト: Pyrdacor/Ambermoon.net
        /// <summary>
        /// The position of the data reader should be at
        /// the start of the option names just behind the
        /// automap names.
        ///
        /// It will be behind the option names after this.
        /// </summary>
        internal OptionNames(IDataReader dataReader)
        {
            foreach (var type in Enum.GetValues <Option>())
            {
                entries.Add(type, dataReader.ReadNullTerminatedString(AmigaExecutable.Encoding));

                if (type == Option.CeilingTexture3D)
                {
                    break; // stop here
                }
            }

            dataReader.AlignToWord();
        }
コード例 #10
0
        /// <summary>
        /// The position of the data reader should be at
        /// the start of the UI texts just behind the
        /// ailment names.
        ///
        /// It will be behind the UI texts after this.
        /// </summary>
        internal UITexts(IDataReader dataReader)
        {
            foreach (var type in Enum.GetValues <UITextIndex>())
            {
                // TODO: This needs improvement!
                var text = dataReader.ReadNullTerminatedString(AmigaExecutable.Encoding);
                text = text.Replace("0123456789", "{1:1111111111}");
                text = text.Replace("012345678", "{1:111111111}");
                text = text.Replace("01234567", "{1:11111111}");
                text = text.Replace("0123456", "{1:1111111}");
                text = text.Replace("012345", "{1:111111}");
                text = text.Replace("01234", "{1:11111}");
                text = text.Replace("0123", "{1:1111}");
                text = text.Replace("012", "{1:111}");
                text = text.Replace("01", "{1:11}");
                text = text.Replace("0", "{1:1}");
                text = text.Replace('1', '0');
                int offset = 0;
                int n      = 0;
                while (offset < text.Length)
                {
                    int index = text.IndexOf("0:", offset);

                    if (index == -1)
                    {
                        break;
                    }

                    if (n == 0)
                    {
                        ++n;
                    }
                    else
                    {
                        text = text.Remove(index, 1);
                        text = text.Insert(index, (n++).ToString());
                    }
                    offset = index + 3;
                }
                entries.Add(type, text);
            }

            dataReader.AlignToWord();
        }
コード例 #11
0
        /// <summary>
        /// The position of the data reader should be at
        /// the start of the song names just behind the
        /// option names.
        ///
        /// It will be behind the song names after this.
        /// </summary>
        internal SongNames(IDataReader dataReader)
        {
            string ReadName()
            {
                var name = dataReader.ReadNullTerminatedString(AmigaExecutable.Encoding);

                if (string.IsNullOrWhiteSpace(name))
                {
                    name = "No name";
                }

                return(name);
            }

            for (int i = 1; i <= NumSongs; ++i)
            {
                entries.Add((Song)i, ReadName());
            }

            dataReader.AlignToWord();
        }
コード例 #12
0
ファイル: WorldNames.cs プロジェクト: Pyrdacor/Ambermoon.net
        /// <summary>
        /// The position of the data reader should be at
        /// the start of the world names just behind the
        /// file list.
        ///
        /// It will be behind the world names after this.
        /// </summary>
        internal WorldNames(IDataReader dataReader)
        {
            var offsets   = new uint[3];
            int endOffset = dataReader.Position;

            for (int i = 0; i < 3; ++i)
            {
                offsets[i] = dataReader.ReadDword();
            }

            for (int i = 0; i < 3; ++i)
            {
                dataReader.Position = (int)offsets[i];
                entries.Add((World)i, dataReader.ReadNullTerminatedString(AmigaExecutable.Encoding));

                if (dataReader.Position > endOffset)
                {
                    endOffset = dataReader.Position;
                }
            }

            dataReader.Position = endOffset;
            dataReader.AlignToWord();
        }
コード例 #13
0
ファイル: FileList.cs プロジェクト: Metibor/Ambermoon
        /// <summary>
        /// The position of the data reader should be at
        /// the start of the file list.
        ///
        /// It will be behind the file list after this.
        /// </summary>
        internal FileList(IDataReader dataReader)
        {
            int numEntries = dataReader.ReadWord() * 4;

            dataReader.ReadWord(); // TODO: always 0?
            var offsets   = new uint[numEntries];
            int endOffset = dataReader.Position;

            for (int i = 0; i < numEntries; ++i)
            {
                offsets[i] = dataReader.ReadDword();
            }

            for (int i = 0; i < numEntries; ++i)
            {
                if (offsets[i] == 0)
                {
                    IndexedEntries.Add(new string[0]);
                    continue;
                }

                dataReader.Position = (int)offsets[i];

                byte diskNumber = dataReader.ReadByte();

                if (dataReader.PeekByte() >= 0x20)
                {
                    if (diskNumber == 0)
                    {
                        throw new AmbermoonException(ExceptionScope.Data, "Invalid disk number 0.");
                    }

                    string filename = dataReader.ReadNullTerminatedString();
                    Entries[filename] = (char)('A' + diskNumber - 1);
                    IndexedEntries.Add(new string[1] {
                        filename
                    });
                }
                else
                {
                    --dataReader.Position;
                    var      diskNumbers  = dataReader.ReadBytes(4);
                    var      baseFileName = dataReader.ReadNullTerminatedString();
                    string[] filenames    = new string[4];

                    for (int d = 0; d < 4; ++d)
                    {
                        if (diskNumbers[d] != 0)
                        {
                            string filename = baseFileName.Replace('0', (char)('1' + d));
                            Entries[filename] = (char)('A' + diskNumbers[d] - 1);
                            filenames[d]      = filename;
                        }
                    }

                    IndexedEntries.Add(filenames);
                }

                if (dataReader.Position > endOffset)
                {
                    endOffset = dataReader.Position;
                }
            }

            dataReader.Position = endOffset;
            dataReader.AlignToWord();
        }
コード例 #14
0
ファイル: Messages.cs プロジェクト: Pyrdacor/Ambermoon.net
        bool ReadText(IDataReader dataReader)
        {
            // The next section starts with an amount of 300 as a dword.
            // If we find it we stop reading by returning false. For safety
            // we will check if the value is lower than 0x1000 as the offsets
            // here will be over 0x8000.
            var next     = dataReader.PeekDword();
            var nextWord = next >> 8;

            if (nextWord > 0x100 && nextWord < 0x1000)
            {
                --dataReader.Position;
                return(false);
            }

            nextWord >>= 8;

            if (nextWord > 0x100 && nextWord < 0x1000)
            {
                dataReader.Position -= 2;
                return(false);
            }

            nextWord >>= 8;

            if (nextWord > 0x100 && nextWord < 0x1000)
            {
                dataReader.Position -= 3;
                return(false);
            }

            if (dataReader.PeekWord() == 0) // offset section / split text with placeholders
            {
                dataReader.AlignToWord();

                if (dataReader.PeekWord() != 0)
                {
                    throw new AmbermoonException(ExceptionScope.Data, "Invalid text section.");
                }

                while (dataReader.PeekDword() == 0)
                {
                    dataReader.Position += 4;
                }

                if (dataReader.PeekByte() != 0)
                {
                    dataReader.Position -= 2;
                }

                string text        = "";
                var    offsets     = new List <uint>();
                int    endOffset   = dataReader.Position;
                uint   firstOffset = uint.MaxValue;

                while (dataReader.PeekByte() == 0 && dataReader.Position < firstOffset)
                {
                    var offset = dataReader.ReadDword();

                    if (offset != 0)
                    {
                        if (offset < firstOffset)
                        {
                            firstOffset = offset;
                        }

                        offsets.Add(offset);
                    }
                }

                for (int i = 0; i < offsets.Count; ++i)
                {
                    dataReader.Position = (int)offsets[i];
                    text += dataReader.ReadNullTerminatedString(AmigaExecutable.Encoding);

                    if (i != offsets.Count - 1) // Insert placeholder
                    {
                        text += "{" + i + "}";
                    }

                    if (dataReader.Position > endOffset)
                    {
                        endOffset = dataReader.Position;
                    }
                }

                entries.Add(text);
                dataReader.Position = endOffset;
            }
            else // just a text
            {
                entries.Add(dataReader.ReadNullTerminatedString(AmigaExecutable.Encoding));

                bool sectionFollows = dataReader.PeekDword() == 0;

                while (dataReader.PeekByte() == 0 || dataReader.PeekByte() == 0xff)
                {
                    if (sectionFollows)
                    {
                        if ((dataReader.PeekDword() & 0x0000ffff) > 0xff)
                        {
                            break;
                        }
                    }
                    else
                    {
                        sectionFollows = dataReader.PeekDword() == 0;
                    }

                    ++dataReader.Position;
                }
            }

            return(true);
        }