Graphic LoadGraphic(Monster monster)
        {
            var file = gameData.Files["Monster_gfx.amb"].Files[(int)monster.CombatGraphicIndex];

            file.Position = 0;
            var graphic       = new Graphic();
            var graphicReader = new GraphicReader();
            var graphicInfo   = new GraphicInfo
            {
                Width         = (int)monster.FrameWidth,
                Height        = (int)monster.FrameHeight,
                GraphicFormat = GraphicFormat.Palette5Bit,
                Alpha         = true,
                PaletteOffset = 0
            };
            int numFrames       = file.Size / ((graphicInfo.Width * graphicInfo.Height * 5 + 7) / 8); // TODO: is this inside monster data?
            var compoundGraphic = new Graphic(numFrames * (int)monster.MappedFrameWidth, (int)monster.MappedFrameHeight, 0);

            for (int i = 0; i < numFrames; ++i)
            {
                graphicReader.ReadGraphic(graphic, file, graphicInfo);
                compoundGraphic.AddOverlay((uint)i * monster.MappedFrameWidth, 0, graphic.CreateScaled((int)monster.MappedFrameWidth, (int)monster.MappedFrameHeight), false);
            }
            for (int i = 0; i < compoundGraphic.Data.Length; ++i)
            {
                compoundGraphic.Data[i] = monster.MonsterPalette[compoundGraphic.Data[i] & 0x1f];
            }
            return(compoundGraphic);
        }
Exemple #2
0
        public static Graphic Concat(params Graphic[] graphics)
        {
            var  concatGraphic = new Graphic(graphics.Sum(g => g.Width), graphics.Max(g => g.Height), 0);
            uint x             = 0;

            foreach (var graphic in graphics)
            {
                concatGraphic.AddOverlay(x, 0, graphic, false);
                x += (uint)graphic.Width;
            }

            return(concatGraphic);
        }
Exemple #3
0
        public static List <Graphic> Create()
        {
            // This is used by the healing animation (falling stars)
            // and the magic item animation (blinking stars).
            // There are 3 frames.
            byte[] redStarFrameData = new byte[]
            {
                // Transparency: 0
                // Red: 20 (CC4433)
                // Orange: 21 (EE6633)
                // Yellow: 16 (FFCC00)
                // White: 1 (EEDDCC)
                // -----------------------
                // 1st frame: Big star
                0, 0, 0, 20, 0, 0, 0,
                0, 0, 0, 21, 0, 0, 0,
                0, 0, 20, 16, 20, 0, 0,
                20, 21, 16, 1, 16, 21, 20,
                0, 0, 20, 16, 20, 0, 0,
                0, 0, 0, 21, 0, 0, 0,
                0, 0, 0, 20, 0, 0, 0,
                // 2nd frame: Small star
                0, 0, 0, 0, 0, 0, 0,
                0, 0, 0, 20, 0, 0, 0,
                0, 0, 0, 21, 0, 0, 0,
                0, 20, 21, 16, 21, 20, 0,
                0, 0, 0, 21, 0, 0, 0,
                0, 0, 0, 20, 0, 0, 0,
                0, 0, 0, 0, 0, 0, 0,
                // 3rd frame: Single orange pixel
                0, 0, 0, 0, 0, 0, 0,
                0, 0, 0, 0, 0, 0, 0,
                0, 0, 0, 0, 0, 0, 0,
                0, 0, 0, 21, 0, 0, 0,
                0, 0, 0, 0, 0, 0, 0,
                0, 0, 0, 0, 0, 0, 0,
                0, 0, 0, 0, 0, 0, 0
            };

            Graphic GetRedStarFrame(int frame)
            {
                return(new Graphic
                {
                    Width = 7,
                    Height = 7,
                    Data = redStarFrameData.Skip(frame * 49).Take(49).ToArray(),
                    IndexedGraphic = true
                });
            }

            Graphic CreateBlinkingStars()
            {
                var stars = new List <Star>();
                var addAmountsPerFrame = new int[] { 1, 1, 0, 1, 0, 0, 0, 0 };
                var random             = new Random();               // always use a new random to produce the same effect
                var animation          = new Graphic(8 * 16, 16, 0); // 11 frames with 16x16

                for (int i = 0; i < 8; ++i)                          // 8 frames in total
                {
                    // in each frame we have several stars in specific states (star frame)
                    var frame = new Graphic(16, 16, 0);

                    // first update existing stars
                    for (int s = stars.Count - 1; s >= 0; --s)
                    {
                        var star = stars[s];

                        if (++star.Frame == 5)
                        {
                            stars.RemoveAt(s);
                        }
                        else
                        {
                            frame.AddOverlay((uint)star.Position.X, (uint)star.Position.Y, GetRedStarFrame(star.Frame > 1 ? star.Frame - 2 : 2 - star.Frame));
                        }
                    }
                    // then add new stars
                    for (int a = 0; a < addAmountsPerFrame[i]; ++a)
                    {
                        var star = new Star
                        {
                            Position = new Position((int)random.Next() % 10, (int)random.Next() % 10),
                            Frame    = 0
                        };
                        stars.Add(star);
                        frame.AddOverlay((uint)star.Position.X, (uint)star.Position.Y, GetRedStarFrame(0));
                    }

                    animation.AddOverlay((uint)i * 16, 0, frame);
                }

                return(animation);
            }

            // See UIElementGraphic
            return(new List <Graphic>
            {
                // Small vertical scrollbar
                GraphicBuilder.Create(6, 28)
                .AddColoredArea(new Rect(0, 0, 1, 1), 31)
                .AddColoredArea(new Rect(1, 0, 4, 1), 30)
                .AddColoredArea(new Rect(5, 0, 1, 1), 28)
                .AddColoredArea(new Rect(0, 1, 1, 25), 30)
                .AddColoredArea(new Rect(1, 1, 4, 25), 29)
                .AddColoredArea(new Rect(5, 1, 1, 25), 27)
                .AddColoredArea(new Rect(0, 26, 1, 1), 28)
                .AddColoredArea(new Rect(1, 26, 5, 1), 27)
                .AddColoredArea(new Rect(0, 27, 6, 1), 26)
                .Build(),

                // Small vertical scrollbar highlighted
                GraphicBuilder.Create(6, 28)
                .AddColoredArea(new Rect(0, 0, 5, 1), 31)
                .AddColoredArea(new Rect(5, 0, 1, 1), 29)
                .AddColoredArea(new Rect(0, 1, 1, 25), 31)
                .AddColoredArea(new Rect(1, 1, 4, 25), 30)
                .AddColoredArea(new Rect(5, 1, 1, 25), 28)
                .AddColoredArea(new Rect(0, 26, 1, 1), 29)
                .AddColoredArea(new Rect(1, 26, 5, 1), 28)
                .AddColoredArea(new Rect(0, 27, 6, 1), 26)
                .Build(),

                // Large vertical scrollbar
                GraphicBuilder.Create(6, 57)
                .AddColoredArea(new Rect(0, 0, 1, 1), 31)
                .AddColoredArea(new Rect(1, 0, 4, 1), 30)
                .AddColoredArea(new Rect(5, 0, 1, 1), 28)
                .AddColoredArea(new Rect(0, 1, 1, 54), 30)
                .AddColoredArea(new Rect(1, 1, 4, 54), 29)
                .AddColoredArea(new Rect(5, 1, 1, 54), 27)
                .AddColoredArea(new Rect(0, 55, 1, 1), 28)
                .AddColoredArea(new Rect(1, 55, 5, 1), 27)
                .AddColoredArea(new Rect(0, 56, 6, 1), 26)
                .Build(),

                // Large vertical scrollbar highlighted
                GraphicBuilder.Create(6, 57)
                .AddColoredArea(new Rect(0, 0, 5, 1), 31)
                .AddColoredArea(new Rect(5, 0, 1, 1), 29)
                .AddColoredArea(new Rect(0, 1, 1, 54), 31)
                .AddColoredArea(new Rect(1, 1, 4, 54), 30)
                .AddColoredArea(new Rect(5, 1, 1, 54), 28)
                .AddColoredArea(new Rect(0, 55, 1, 1), 29)
                .AddColoredArea(new Rect(1, 55, 5, 1), 28)
                .AddColoredArea(new Rect(0, 56, 6, 1), 26)
                .Build(),

                // Small vertical scrollbar background
                GraphicBuilder.Create(6, 53)
                .AddColoredArea(new Rect(1, 1, 5, 52), 27)
                .AddColoredArea(new Rect(0, 1, 1, 52), 26)
                .AddColoredArea(new Rect(0, 0, 6, 1), 26)
                .Build(),

                // Small vertical scrollbar disabled
                GraphicBuilder.Create(6, 53)
                .AddColoredArea(new Rect(0, 0, 1, 1), 31)
                .AddColoredArea(new Rect(1, 0, 4, 1), 30)
                .AddColoredArea(new Rect(5, 0, 1, 1), 32)
                .AddColoredArea(new Rect(0, 1, 1, 51), 30)
                .AddColoredArea(new Rect(1, 1, 4, 51), 28)
                .AddColoredArea(new Rect(5, 1, 1, 51), 26)
                .AddColoredArea(new Rect(0, 52, 1, 1), 32)
                .AddColoredArea(new Rect(1, 52, 5, 1), 26)
                .Build(),

                // Large vertical scrollbar background
                GraphicBuilder.Create(6, 112)
                .AddColoredArea(new Rect(1, 1, 5, 111), 27)
                .AddColoredArea(new Rect(0, 1, 1, 111), 26)
                .AddColoredArea(new Rect(0, 0, 6, 1), 26)
                .Build(),

                // Large vertical scrollbar disabled
                GraphicBuilder.Create(6, 112)
                .AddColoredArea(new Rect(0, 0, 1, 1), 31)
                .AddColoredArea(new Rect(1, 0, 4, 1), 30)
                .AddColoredArea(new Rect(5, 0, 1, 1), 32)
                .AddColoredArea(new Rect(0, 1, 1, 110), 30)
                .AddColoredArea(new Rect(1, 1, 4, 110), 28)
                .AddColoredArea(new Rect(5, 1, 1, 110), 26)
                .AddColoredArea(new Rect(0, 111, 1, 1), 32)
                .AddColoredArea(new Rect(1, 111, 5, 1), 26)
                .Build(),

                // Item slot background
                new Graphic(16, 24, 27),

                // Item slot disabled
                GraphicBuilder.Create(16, 24)
                .AddColoredArea(new Rect(0, 0, 1, 1), 31)
                .AddColoredArea(new Rect(1, 0, 14, 1), 30)
                .AddColoredArea(new Rect(15, 0, 1, 1), 32)
                .AddColoredArea(new Rect(0, 1, 1, 22), 30)
                .AddColoredArea(new Rect(1, 1, 14, 22), 28)
                .AddColoredArea(new Rect(15, 1, 1, 22), 26)
                .AddColoredArea(new Rect(0, 23, 1, 1), 32)
                .AddColoredArea(new Rect(1, 23, 15, 1), 26)
                .Build(),

                // Portrait background
                Graphic.CreateGradient(32, 34, 4, 2, 8, 23),

                // Thin portrait border
                Graphic.FromIndexedData(32, 1, new byte[32]
                {
                    28, 28, 28, 28, 27, 28, 27, 28, 27, 28, 27, 28, 27, 28, 27, 28,
                    28, 27, 28, 27, 28, 27, 28, 27, 28, 27, 28, 27, 28, 28, 28, 28
                }),

                // Map disable overlay (UI palette-> 32 = black, 0 = transparent)
                Graphic.FromIndexedData(320, 144, Enumerable.Range(0, 320 * 144).Select(i => (byte)((i + i / 320) % 2 == 0 ? 0 : 32)).ToArray()),

                // Ambermoon info box (shown over the map when opening option menu)
                GraphicBuilder.Create(128, 19)
                .AddColoredArea(new Rect(0, 0, 1, 1), 31)
                .AddColoredArea(new Rect(1, 0, 126, 1), 30)
                .AddColoredArea(new Rect(127, 0, 1, 1), 27)
                .AddColoredArea(new Rect(0, 1, 1, 17), 30)
                .AddColoredArea(new Rect(1, 1, 126, 17), 28)
                .AddColoredArea(new Rect(127, 1, 1, 17), 26)
                .AddColoredArea(new Rect(0, 18, 1, 1), 27)
                .AddColoredArea(new Rect(1, 18, 127, 1), 26)
                .Build(),

                // Bigger info box
                GraphicBuilder.Create(144, 26)
                .AddColoredArea(new Rect(0, 0, 1, 1), 31)
                .AddColoredArea(new Rect(1, 0, 142, 1), 30)
                .AddColoredArea(new Rect(143, 0, 1, 1), 27)
                .AddColoredArea(new Rect(0, 1, 1, 24), 30)
                .AddColoredArea(new Rect(1, 1, 142, 24), 28)
                .AddColoredArea(new Rect(143, 1, 1, 24), 26)
                .AddColoredArea(new Rect(0, 25, 1, 1), 27)
                .AddColoredArea(new Rect(1, 25, 143, 1), 26)
                .Build(),

                // BattleFieldYellowBorder
                GraphicBuilder.Create(16, 13)
                .AddColoredArea(new Rect(0, 0, 16, 1), Color.ActivePartyMember)
                .AddColoredArea(new Rect(0, 1, 1, 11), Color.ActivePartyMember)
                .AddColoredArea(new Rect(15, 1, 1, 11), Color.ActivePartyMember)
                .AddColoredArea(new Rect(0, 12, 16, 1), Color.ActivePartyMember)
                .Build(),

                // BattleFieldOrangeBorder
                GraphicBuilder.Create(16, 13)
                .AddColoredArea(new Rect(0, 0, 16, 1), Color.LightRed)
                .AddColoredArea(new Rect(0, 1, 1, 11), Color.LightRed)
                .AddColoredArea(new Rect(15, 1, 1, 11), Color.LightRed)
                .AddColoredArea(new Rect(0, 12, 16, 1), Color.LightRed)
                .Build(),

                // BattleFieldGreenHighlight
                GraphicBuilder.Create(16, 13)
                .AddColoredArea(new Rect(1, 1, 14, 11), Color.LightGreen)
                .Build(),

                // HealingStarAnimation (3 frames of a redish star)
                Graphic.FromIndexedData(7 * 3, 7, redStarFrameData),

                // BattleFieldBlockedMovementCursor
                Graphic.FromIndexedData(14, 11, new byte[14 * 11]
                {
                    // Transparency: 0
                    // Red: 19 (881122)
                    // -----------------------
                    0, 19, 19, 0, 0, 0, 0, 0, 0, 0, 19, 19, 19, 0,
                    19, 19, 19, 19, 19, 0, 0, 0, 19, 19, 19, 19, 19, 19,
                    19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 0,
                    0, 0, 19, 19, 19, 19, 19, 19, 19, 19, 19, 0, 0, 0,
                    0, 0, 0, 0, 19, 19, 19, 19, 19, 19, 0, 0, 0, 0,
                    0, 0, 0, 19, 19, 19, 19, 19, 19, 19, 19, 0, 0, 0,
                    0, 0, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 0,
                    0, 19, 19, 19, 19, 0, 0, 0, 19, 19, 19, 19, 19, 19,
                    19, 19, 19, 19, 0, 0, 0, 0, 0, 0, 19, 19, 19, 19,
                    19, 19, 19, 19, 0, 0, 0, 0, 0, 0, 0, 19, 19, 0,
                    0, 19, 19, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
                }),

                // ItemMagicAnimation
                CreateBlinkingStars(),

                // BrokenItemOverlay
                Graphic.FromIndexedData(16, 16, new byte[16 * 16]
                {
                    // Transparency: 0
                    // Dark gray: 26 (222222)
                    // -----------------------
                    0, 0, 0, 0, 0, 0, 0, 0, 0, 26, 26, 26, 26, 0, 0, 0,
                    0, 0, 0, 0, 0, 0, 0, 0, 0, 26, 26, 26, 0, 0, 0, 0,
                    0, 0, 26, 0, 0, 26, 0, 0, 26, 26, 26, 0, 0, 0, 0, 0,
                    0, 0, 0, 0, 0, 0, 26, 26, 26, 0, 0, 0, 0, 0, 0, 0,
                    26, 26, 0, 0, 0, 0, 0, 26, 26, 0, 0, 0, 0, 0, 0, 0,
                    26, 26, 26, 26, 0, 0, 0, 26, 26, 0, 0, 0, 0, 26, 0, 0,
                    26, 26, 26, 26, 26, 26, 0, 26, 26, 0, 0, 0, 0, 0, 0, 0,
                    0, 0, 26, 26, 26, 26, 26, 26, 26, 26, 0, 0, 0, 0, 0, 0,
                    0, 0, 0, 26, 0, 26, 26, 26, 26, 26, 0, 0, 0, 26, 0, 0,
                    0, 0, 26, 0, 0, 0, 0, 0, 0, 26, 26, 26, 26, 26, 26, 26,
                    0, 0, 0, 0, 0, 0, 0, 0, 0, 26, 26, 26, 26, 26, 26, 0,
                    0, 0, 0, 26, 0, 0, 0, 0, 0, 26, 0, 0, 0, 0, 0, 0,
                    0, 0, 0, 0, 0, 0, 0, 0, 26, 0, 0, 0, 0, 0, 0, 0,
                    0, 0, 0, 0, 0, 0, 0, 26, 0, 0, 0, 0, 26, 0, 0, 0,
                    0, 0, 0, 0, 0, 26, 26, 26, 0, 0, 0, 26, 0, 0, 0, 0,
                    0, 0, 0, 26, 26, 26, 26, 0, 26, 0, 0, 26, 0, 0, 0, 0,
                }),

                // AutomapWallFrames
                Graphic.Concat
                (
                    // Map background: 6
                    // Wall color: 7
                    // -----------------------
                    // End pieces
                    Graphic.FromIndexedData(32, 8, new byte[32 * 8]
                {
                    //  top open         right open       bottom open        left open
                    6, 7, 7, 6, 6, 7, 7, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
                    6, 7, 7, 6, 6, 7, 7, 6, 6, 7, 7, 7, 7, 7, 7, 7, 6, 7, 7, 7, 7, 7, 7, 6, 7, 7, 7, 7, 7, 7, 7, 6,
                    6, 7, 7, 6, 6, 7, 7, 6, 6, 7, 7, 7, 7, 7, 7, 7, 6, 7, 7, 7, 7, 7, 7, 6, 7, 7, 7, 7, 7, 7, 7, 6,
                    6, 7, 7, 6, 6, 7, 7, 6, 6, 7, 7, 6, 6, 6, 6, 6, 6, 7, 7, 6, 6, 7, 7, 6, 6, 6, 6, 6, 6, 7, 7, 6,
                    6, 7, 7, 6, 6, 7, 7, 6, 6, 7, 7, 6, 6, 6, 6, 6, 6, 7, 7, 6, 6, 7, 7, 6, 6, 6, 6, 6, 6, 7, 7, 6,
                    6, 7, 7, 7, 7, 7, 7, 6, 6, 7, 7, 7, 7, 7, 7, 7, 6, 7, 7, 6, 6, 7, 7, 6, 7, 7, 7, 7, 7, 7, 7, 6,
                    6, 7, 7, 7, 7, 7, 7, 6, 6, 7, 7, 7, 7, 7, 7, 7, 6, 7, 7, 6, 6, 7, 7, 6, 7, 7, 7, 7, 7, 7, 7, 6,
                    6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 7, 7, 6, 6, 7, 7, 6, 6, 6, 6, 6, 6, 6, 6, 6,
                }),
                    // Corners
                    Graphic.FromIndexedData(32, 8, new byte[32 * 8]
                {
                    //  b+r open          b+l open      //  t+r open          t+l open
                    6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 7, 7, 6, 6, 7, 7, 6, 6, 7, 7, 6, 6, 7, 7, 6,
                    6, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 6, 6, 7, 7, 6, 6, 7, 7, 7, 7, 7, 7, 6, 6, 7, 7, 6,
                    6, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 6, 6, 7, 7, 6, 6, 7, 7, 7, 7, 7, 7, 6, 6, 7, 7, 6,
                    6, 7, 7, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 7, 7, 6, 6, 7, 7, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 7, 7, 6,
                    6, 7, 7, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 7, 7, 6, 6, 7, 7, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 7, 7, 6,
                    6, 7, 7, 6, 6, 7, 7, 7, 7, 7, 7, 6, 6, 7, 7, 6, 6, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 6,
                    6, 7, 7, 6, 6, 7, 7, 7, 7, 7, 7, 6, 6, 7, 7, 6, 6, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 6,
                    6, 7, 7, 6, 6, 7, 7, 6, 6, 7, 7, 6, 6, 7, 7, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
                }),
                    // T-crossings
                    Graphic.FromIndexedData(32, 8, new byte[32 * 8]
                {
                    // t+l+r open        t+b+r open        b+l+r open        t+b+l open
                    6, 7, 7, 6, 6, 7, 7, 6, 6, 7, 7, 6, 6, 7, 7, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 7, 7, 6, 6, 7, 7, 6,
                    7, 7, 7, 6, 6, 7, 7, 7, 6, 7, 7, 6, 6, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 6, 6, 7, 7, 6,
                    7, 7, 7, 6, 6, 7, 7, 7, 6, 7, 7, 6, 6, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 6, 6, 7, 7, 6,
                    6, 6, 6, 6, 6, 6, 6, 6, 6, 7, 7, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 7, 7, 6,
                    6, 6, 6, 6, 6, 6, 6, 6, 6, 7, 7, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 7, 7, 6,
                    7, 7, 7, 7, 7, 7, 7, 7, 6, 7, 7, 6, 6, 7, 7, 7, 7, 7, 7, 6, 6, 7, 7, 7, 7, 7, 7, 6, 6, 7, 7, 6,
                    7, 7, 7, 7, 7, 7, 7, 7, 6, 7, 7, 6, 6, 7, 7, 7, 7, 7, 7, 6, 6, 7, 7, 7, 7, 7, 7, 6, 6, 7, 7, 6,
                    6, 6, 6, 6, 6, 6, 6, 6, 6, 7, 7, 6, 6, 7, 7, 6, 6, 7, 7, 6, 6, 7, 7, 6, 6, 7, 7, 6, 6, 7, 7, 6,
                }),
                    // crossing, vertical and horizontal piece and single closed tile
                    Graphic.FromIndexedData(32, 8, new byte[32 * 8]
                {
                    //  all open          t+b open          l+r open           Closed
                    6, 7, 7, 6, 6, 7, 7, 6, 6, 7, 7, 6, 6, 7, 7, 6, 6, 6, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 7,
                    7, 7, 7, 6, 6, 7, 7, 7, 6, 7, 7, 6, 6, 7, 7, 6, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
                    7, 7, 7, 6, 6, 7, 7, 7, 6, 7, 7, 6, 6, 7, 7, 6, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 6, 6, 6, 6, 7, 7,
                    6, 6, 6, 6, 6, 6, 6, 6, 6, 7, 7, 6, 6, 7, 7, 6, 6, 6, 6, 6, 6, 6, 6, 6, 7, 7, 6, 6, 6, 6, 7, 7,
                    6, 6, 6, 6, 6, 6, 6, 6, 6, 7, 7, 6, 6, 7, 7, 6, 6, 6, 6, 6, 6, 6, 6, 6, 7, 7, 6, 6, 6, 6, 7, 7,
                    7, 7, 7, 6, 6, 7, 7, 7, 6, 7, 7, 6, 6, 7, 7, 6, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 6, 6, 6, 6, 7, 7,
                    7, 7, 7, 6, 6, 7, 7, 7, 6, 7, 7, 6, 6, 7, 7, 6, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
                    6, 7, 7, 6, 6, 7, 7, 6, 6, 7, 7, 6, 6, 7, 7, 6, 6, 6, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 7,
                })
                ),

                // FakeWallOverlay
                Graphic.FromIndexedData(8, 8, new byte[8 * 8]
                {
                    6, 0, 6, 0, 6, 0, 6, 0,
                    0, 6, 0, 6, 0, 6, 0, 6,
                    6, 0, 6, 0, 6, 0, 6, 0,
                    0, 6, 0, 6, 0, 6, 0, 6,
                    6, 0, 6, 0, 6, 0, 6, 0,
                    0, 6, 0, 6, 0, 6, 0, 6,
                    6, 0, 6, 0, 6, 0, 6, 0,
                    0, 6, 0, 6, 0, 6, 0, 6,
                })
            });
        }
Exemple #4
0
        internal UIGraphics(IDataReader dataReader)
        {
            var graphicReader = new GraphicReader();
            var graphicInfo   = new GraphicInfo
            {
                Width         = 16,
                Height        = 6,
                Alpha         = true,
                GraphicFormat = GraphicFormat.Palette3Bit,
                PaletteOffset = 24
            };

            Graphic ReadGraphic(IDataReader dataReader, byte maskColor = 0)
            {
                var graphic = new Graphic();

                graphicReader.ReadGraphic(graphic, dataReader, graphicInfo, maskColor);

                return(graphic);
            }

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

                graphicReader.ReadGraphic(graphic, dataReader, graphicInfo);
                graphic.ReplaceColor(0, 32);

                return(graphic);
            }

            // Note: First 156 bytes seem to be some offsets etc.

            dataReader.Position = 156;
            entries.Add(UIGraphic.DisabledOverlay16x6, ReadGraphic(dataReader));
            graphicInfo.Height = 16;
            // window frames
            entries.Add(UIGraphic.FrameUpperLeft, ReadGraphic(dataReader));
            entries.Add(UIGraphic.FrameLeft, ReadGraphic(dataReader));
            entries.Add(UIGraphic.FrameLowerLeft, ReadGraphic(dataReader));
            entries.Add(UIGraphic.FrameTop, ReadGraphic(dataReader));
            entries.Add(UIGraphic.FrameBottom, ReadGraphic(dataReader));
            entries.Add(UIGraphic.FrameUpperRight, ReadGraphic(dataReader));
            entries.Add(UIGraphic.FrameRight, ReadGraphic(dataReader));
            entries.Add(UIGraphic.FrameLowerRight, ReadGraphic(dataReader));

            graphicInfo.GraphicFormat = GraphicFormat.Palette5Bit;
            graphicInfo.PaletteOffset = 0;
            for (int i = (int)UIGraphic.StatusDead; i <= (int)UIGraphic.StatusRangeAttack; ++i)
            {
                entries.Add((UIGraphic)i, ReadGraphic(dataReader));
            }

            graphicInfo.Width         = 32;
            graphicInfo.Height        = 29;
            graphicInfo.GraphicFormat = GraphicFormat.Palette5Bit;
            graphicInfo.PaletteOffset = 0;
            entries.Add(UIGraphic.Eagle, ReadGraphic(dataReader));
            graphicInfo.Height = 26;
            entries.Add(UIGraphic.Explosion, ReadGraphic(dataReader));
            graphicInfo.Height        = 23;
            graphicInfo.GraphicFormat = GraphicFormat.Palette3Bit;
            graphicInfo.PaletteOffset = 24;
            entries.Add(UIGraphic.Ouch, ReadGraphic(dataReader));

            graphicInfo.Width  = 16;
            graphicInfo.Height = 60;
            entries.Add(UIGraphic.StarBlinkAnimation, ReadGraphic(dataReader));
            graphicInfo.Height = 40;
            entries.Add(UIGraphic.PlusBlinkAnimation, ReadGraphic(dataReader));
            graphicInfo.Height = 36;
            entries.Add(UIGraphic.LeftPortraitBorder, ReadGraphic(dataReader));
            entries.Add(UIGraphic.CharacterValueBarFrames, ReadGraphic(dataReader));
            entries.Add(UIGraphic.RightPortraitBorder, ReadGraphic(dataReader));
            graphicInfo.Height = 1;
            entries.Add(UIGraphic.SmallBorder1, ReadGraphic(dataReader));
            entries.Add(UIGraphic.SmallBorder2, ReadGraphic(dataReader));
            graphicInfo.Height = 16;
            for (int i = (int)UIGraphic.Candle; i <= (int)UIGraphic.Map; ++i)
            {
                entries.Add((UIGraphic)i, ReadOpaqueGraphic(dataReader));
            }

            graphicInfo.Width  = 32;
            graphicInfo.Height = 15;
            entries.Add(UIGraphic.Windchain, ReadOpaqueGraphic(dataReader));
            graphicInfo.Height = 32;
            entries.Add(UIGraphic.MonsterEyeInactive, ReadOpaqueGraphic(dataReader));
            entries.Add(UIGraphic.MonsterEyeActive, ReadOpaqueGraphic(dataReader));
            entries.Add(UIGraphic.Night, ReadOpaqueGraphic(dataReader));
            entries.Add(UIGraphic.Dusk, ReadOpaqueGraphic(dataReader));
            entries.Add(UIGraphic.Day, ReadOpaqueGraphic(dataReader));
            entries.Add(UIGraphic.Dawn, ReadOpaqueGraphic(dataReader));

            graphicInfo.Height = 17;
            graphicInfo.Alpha  = true;
            entries.Add(UIGraphic.ButtonFrame, ReadGraphic(dataReader));
            entries.Add(UIGraphic.ButtonFramePressed, ReadGraphic(dataReader));
            // Note: There is a 1-bit mask here where a 0 bit means transparent (keep color) and 1 means overlay.
            // As we use this for buttons we will set the color as the button back color (28).
            // The disable overlay is 32x11 in size.
            var disableOverlay = new Graphic(32, 11, 0);

            for (int y = 0; y < 11; ++y)
            {
                var bits = dataReader.ReadDword();

                for (int x = 0; x < 32; ++x)
                {
                    if ((bits & 0x80000000) != 0)
                    {
                        disableOverlay.Data[y * 32 + x] = 28;
                    }
                    bits <<= 1;
                }
            }
            entries.Add(UIGraphic.ButtonDisabledOverlay, disableOverlay);
            graphicInfo.Width  = 32;
            graphicInfo.Height = 32;
            entries.Add(UIGraphic.Compass, ReadOpaqueGraphic(dataReader));
            graphicInfo.Width  = 16;
            graphicInfo.Height = 9;
            entries.Add(UIGraphic.Attack, ReadGraphic(dataReader));
            entries.Add(UIGraphic.Defense, ReadGraphic(dataReader));
            graphicInfo.Width  = 32;
            graphicInfo.Height = 34;
            entries.Add(UIGraphic.Skull, ReadGraphic(dataReader, 25));
            entries.Add(UIGraphic.EmptyCharacterSlot, ReadOpaqueGraphic(dataReader));
            graphicInfo.Width         = 16;
            graphicInfo.Height        = 16;
            graphicInfo.GraphicFormat = GraphicFormat.Palette3Bit;
            graphicInfo.PaletteOffset = 0;
            var compoundGraphic = new Graphic(176, 16, 0);

            for (uint i = 0; i < 11; ++i)
            {
                compoundGraphic.AddOverlay(i * 16u, 0u, ReadGraphic(dataReader), false);
            }
            entries.Add(UIGraphic.ItemConsume, compoundGraphic);
            graphicInfo.Width         = 32;
            graphicInfo.Height        = 29;
            graphicInfo.GraphicFormat = GraphicFormat.Palette5Bit;
            graphicInfo.PaletteOffset = 0;
            entries.Add(UIGraphic.Talisman, ReadGraphic(dataReader));
            graphicInfo.Width         = 16;
            graphicInfo.Height        = 47;
            graphicInfo.GraphicFormat = GraphicFormat.Palette3Bit;
            graphicInfo.PaletteOffset = 24;
            entries.Add(UIGraphic.UnknownChain, ReadGraphic(dataReader));
            graphicInfo.Width  = 8;
            graphicInfo.Height = 84;
            entries.Add(UIGraphic.BorderWithTriangles, ReadGraphic(dataReader));
        }
Exemple #5
0
        public IntroData(GameData gameData)
        {
            var introHunks = AmigaExecutable.Read(gameData.Files["Ambermoon_intro"].Files[1])
                             .Where(h => h.Type == AmigaExecutable.HunkType.Data).Select(h => new DataReader(((AmigaExecutable.Hunk)h).Data))
                             .ToList();
            var graphicReader = new GraphicReader();

            #region Hunk 0 - Palettes and texts

            var hunk0 = introHunks[0];

            Graphic LoadPalette()
            {
                var paletteGraphic = new Graphic();

                graphicReader.ReadGraphic(paletteGraphic, hunk0, paletteGraphicInfo);
                return(paletteGraphic);
            }

            for (int i = 0; i < 9; ++i)
            {
                introPalettes.Add(LoadPalette());
            }

            hunk0.Position += 8; // 8 unknown bytes

            for (int i = 0; i < 8; ++i)
            {
                byte startByte = hunk0.PeekByte();
                if (startByte != 0x20 && (startByte < 'A' || startByte > 'Z'))
                {
                    ++hunk0.Position; // Sometimes there is an unknown start byte
                }
                texts.Add((IntroText)i, hunk0.ReadNullTerminatedString());
            }

            if (hunk0.ReadByte() != 4) // Should contain the amount of main menu text (= 4)
            {
                throw new AmbermoonException(ExceptionScope.Data, "Wrong intro data.");
            }

            for (int i = 0; i < 4; ++i)
            {
                // The 4 main menu texts are prefixed by 2 bytes (x and y render offset).
                hunk0.Position += 2; // We skip those bytes here.
                texts.Add((IntroText)(8 + i), hunk0.ReadNullTerminatedString());
            }

            // TODO: the credits will follow

            #endregion

            #region Hunk 1 - Main menu background and town graphics

            Size[] hunk1ImageSizes = new Size[8]
            {
                new Size(96, 300), // not sure
                new Size(320, 256),
                new Size(160, 128),
                new Size(160, 128),
                new Size(160, 128),
                new Size(160, 128),
                new Size(160, 128),
                new Size(160, 128)
            };

            for (int i = 0; i < 8; ++i)
            {
                var reader = introHunks[1];

                if (reader.PeekDword() == 0x494d5021) // "IMP!", may be imploded
                {
                    reader = new DataReader(Deploder.DeplodeFimp(reader).Reverse().ToArray());
                }

                var graphicInfo = new GraphicInfo
                {
                    Width         = hunk1ImageSizes[i].Width,
                    Height        = hunk1ImageSizes[i].Height,
                    GraphicFormat = GraphicFormat.Palette4Bit,
                    PaletteOffset = 0,
                    Alpha         = false
                };
                var graphic = new Graphic();
                graphicReader.ReadGraphic(graphic, reader, graphicInfo);
                graphics.Add((IntroGraphic)i, graphic);
            }

            #endregion

            #region Hunk 2 - Unknown

            // TODO

            #endregion

            #region Hunk 3 - Intro graphics (planets, etc)

            Size[] hunk3ImageSizes = new Size[6]
            {
                new Size(128, 82),  // Thalion Logo
                new Size(64, 64),   // Sun
                new Size(128, 128), // Lyramion
                new Size(64, 64),   // Morag
                new Size(64, 64),   // Forest Moon
                new Size(96, 96),   // Meteor
                // TODO ...
            };
            int[] hunk3FrameCounts = new int[6]
            {
                1,
                12,
                1,
                1,
                1,
                1,
                // TODO ...
            };

            for (int i = 0; i < 6; ++i)
            {
                var graphicInfo = new GraphicInfo
                {
                    Width         = hunk3ImageSizes[i].Width,
                    Height        = hunk3ImageSizes[i].Height,
                    GraphicFormat = GraphicFormat.Palette4Bit,
                    PaletteOffset = 0,
                    Alpha         = false
                };
                Graphic graphic;
                int     frames = hunk3FrameCounts[i];
                if (frames == 1)
                {
                    graphic = new Graphic();
                    graphicReader.ReadGraphic(graphic, introHunks[3], graphicInfo);
                }
                else
                {
                    graphic = new Graphic(frames * graphicInfo.Width, graphicInfo.Height, 0);

                    for (int f = 0; f < frames; ++f)
                    {
                        var frameGraphic = new Graphic();
                        graphicReader.ReadGraphic(frameGraphic, introHunks[3], graphicInfo);
                        graphic.AddOverlay((uint)(f * frameGraphic.Width), 0, frameGraphic, false);
                    }
                }
                graphics.Add(IntroGraphic.ThalionLogo + i, graphic);
                if (i == 0) // The other graphics start at 0x42B8 (the data between is unknown yet)
                {
                    introHunks[3].Position = 0x42B8;
                }
            }

            // TODO ...

            #endregion
        }
Exemple #6
0
        public void ReadLabdata(Labdata labdata, IDataReader dataReader, IGameData gameData)
        {
            labdata.WallHeight        = dataReader.ReadWord();
            labdata.CombatBackground  = dataReader.ReadWord() & 0x0fu;
            labdata.CeilingColorIndex = dataReader.ReadByte();
            labdata.FloorColorIndex   = dataReader.ReadByte();
            // Note: The ceiling texture index can be 0 in which case a sky is used.
            //       The sky is composed of a color gradient and a lab background
            //       which is given inside the map data.
            // To be more precisely if the texture index (ceiling and also floor) is
            // 0, the color index is used to draw instead. For example the town of
            // S'Angrila doesn't use a floor texture but only a color.
            uint ceilingTextureIndex = dataReader.ReadByte();
            uint floorTextureIndex   = dataReader.ReadByte();

            labdata.Objects.Clear();
            int numObjects = dataReader.ReadWord();
            var objects    = new List <Tuple <ushort, List <Tuple <short, short, short, int> > > >(numObjects);

            for (int i = 0; i < numObjects; ++i)
            {
                var obj = Tuple.Create(dataReader.ReadWord(), new List <Tuple <short, short, short, int> >(8));

                for (int n = 0; n < 8; ++n) // 8 sub entries (a map object can consist of up to 8 sub objects)
                {
                    obj.Item2.Add(Tuple.Create(
                                      (short)dataReader.ReadWord(),
                                      (short)dataReader.ReadWord(),
                                      (short)dataReader.ReadWord(),
                                      (int)dataReader.ReadWord()));
                }

                objects.Add(obj);
            }

            labdata.ObjectInfos.Clear();
            int numObjectInfos = dataReader.ReadWord();

            for (int i = 0; i < numObjectInfos; ++i)
            {
                var objectInfo = new Labdata.ObjectInfo
                {
                    Flags               = (Tileset.TileFlags)dataReader.ReadDword(),
                    TextureIndex        = dataReader.ReadWord(),
                    NumAnimationFrames  = dataReader.ReadByte(),
                    ColorIndex          = dataReader.ReadByte(),
                    TextureWidth        = dataReader.ReadByte(),
                    TextureHeight       = dataReader.ReadByte(),
                    MappedTextureWidth  = dataReader.ReadWord(),
                    MappedTextureHeight = dataReader.ReadWord()
                };

                labdata.ObjectInfos.Add(objectInfo);
            }

            foreach (var obj in objects)
            {
                var subObjects = new List <Labdata.ObjectPosition>(8);

                foreach (var pos in obj.Item2)
                {
                    if (pos.Item4 != 0)
                    {
                        subObjects.Add(new Labdata.ObjectPosition
                        {
                            X      = pos.Item1,
                            Y      = pos.Item2,
                            Z      = pos.Item3,
                            Object = labdata.ObjectInfos[pos.Item4 - 1]
                        });
                    }
                }

                labdata.Objects.Add(new Labdata.Object
                {
                    AutomapType = (AutomapType)obj.Item1,
                    SubObjects  = subObjects
                });
            }

            labdata.Walls.Clear();
            int numWalls = dataReader.ReadWord();

            for (int i = 0; i < numWalls; ++i)
            {
                var wallData = new Labdata.WallData
                {
                    Flags        = (Tileset.TileFlags)dataReader.ReadDword(),
                    TextureIndex = dataReader.ReadByte(),
                    AutomapType  = (AutomapType)dataReader.ReadByte(),
                    ColorIndex   = dataReader.ReadByte()
                };
                int numOverlays = dataReader.ReadByte();
                if (numOverlays != 0)
                {
                    wallData.Overlays = new Labdata.OverlayData[numOverlays];

                    for (int o = 0; o < numOverlays; ++o)
                    {
                        wallData.Overlays[o] = new Labdata.OverlayData
                        {
                            Blend         = dataReader.ReadByte() != 0,
                            TextureIndex  = dataReader.ReadByte(),
                            PositionX     = dataReader.ReadByte(),
                            PositionY     = dataReader.ReadByte(),
                            TextureWidth  = dataReader.ReadByte(),
                            TextureHeight = dataReader.ReadByte()
                        };
                    }
                }
                labdata.Walls.Add(wallData);
            }

            // Load labyrinth graphics
            var graphicReader = new GraphicReader();

            if (floorTextureIndex != 0)
            {
                labdata.FloorGraphic = ReadGraphic(graphicReader, gameData.Files["Floors.amb"].Files[(int)floorTextureIndex], 64, 64, false, false, true);
            }
            if (ceilingTextureIndex != 0)
            {
                labdata.CeilingGraphic = ReadGraphic(graphicReader, gameData.Files["Floors.amb"].Files[(int)ceilingTextureIndex], 64, 64, false, false, true);
            }
            var objectTextureFiles = gameData.Files[$"2Object3D.amb"].Files;

            gameData.Files[$"3Object3D.amb"].Files.ToList().ForEach(f => objectTextureFiles[f.Key] = f.Value);
            labdata.ObjectGraphics.Clear();
            foreach (var objectInfo in labdata.ObjectInfos)
            {
                if (objectInfo.NumAnimationFrames == 1)
                {
                    labdata.ObjectGraphics.Add(ReadGraphic(graphicReader, objectTextureFiles[(int)objectInfo.TextureIndex],
                                                           (int)objectInfo.TextureWidth, (int)objectInfo.TextureHeight, true, true, true));
                }
                else
                {
                    var compoundGraphic = new Graphic((int)objectInfo.NumAnimationFrames * (int)objectInfo.TextureWidth,
                                                      (int)objectInfo.TextureHeight, 0);

                    for (uint i = 0; i < objectInfo.NumAnimationFrames; ++i)
                    {
                        var partialGraphic = ReadGraphic(graphicReader, objectTextureFiles[(int)objectInfo.TextureIndex],
                                                         (int)objectInfo.TextureWidth, (int)objectInfo.TextureHeight, true, true, i == 0);

                        compoundGraphic.AddOverlay(i * objectInfo.TextureWidth, 0u, partialGraphic, false);
                    }

                    labdata.ObjectGraphics.Add(compoundGraphic);
                }
            }
            var wallTextureFiles    = gameData.Files[$"2Wall3D.amb"].Files;
            var overlayTextureFiles = gameData.Files[$"2Overlay3D.amb"].Files;

            gameData.Files[$"3Wall3D.amb"].Files.ToList().ForEach(f => wallTextureFiles[f.Key]       = f.Value);
            gameData.Files[$"3Overlay3D.amb"].Files.ToList().ForEach(f => overlayTextureFiles[f.Key] = f.Value);
            labdata.WallGraphics.Clear();
            int wallIndex = 0;

            foreach (var wall in labdata.Walls)
            {
                var wallGraphic = ReadGraphic(graphicReader, wallTextureFiles[(int)wall.TextureIndex],
                                              128, 80, wall.Flags.HasFlag(Tileset.TileFlags.Transparency), true, true);

                labdata.WallGraphics.Add(wallGraphic);

                if (wall.Overlays != null && wall.Overlays.Length != 0)
                {
                    foreach (var overlay in wall.Overlays)
                    {
                        wallGraphic.AddOverlay(overlay.PositionX, overlay.PositionY, ReadGraphic(graphicReader,
                                                                                                 overlayTextureFiles[(int)overlay.TextureIndex], (int)overlay.TextureWidth, (int)overlay.TextureHeight, true, true, true),
                                               overlay.Blend);
                    }
                }

                ++wallIndex;
            }
        }
        public GraphicProvider(GameData gameData, ExecutableData.ExecutableData executableData,
                               IntroData introData, OutroData outroData)
        {
            this.gameData = gameData;
            var graphicReader = new GraphicReader();

            Palettes = gameData.Files[paletteFile].Files.ToDictionary(f => f.Key, f => ReadPalette(graphicReader, f.Value));

            // Add builtin palettes
            for (int i = 0; i < 3; ++i)
            {
                Palettes.Add(50 + i, executableData.BuiltinPalettes[i]);
            }

            // And another palette for some UI graphics.
            // The portraits have a blue gradient as background. It is also 32x34 pixels in size and the gradient
            // is in y-direction. All colors have R=0x00 and G=0x11. The blue component is increased by 0x11
            // every 2 pixels starting at y=4 (first 4 pixel rows have B=0x00, next 2 have B=0x11, etc).
            // Last 2 rows have B=0xff.
            Palettes.Add(53, new Graphic
            {
                Width          = 32,
                Height         = 1,
                IndexedGraphic = false,
                Data           = new byte[]
                {
                    // The first colors are used for spells which use a materialize animation (earth and wind spells, waterfall, etc).
                    // The animation uses black, dark red, light purple, dark purple, dark beige, light beige in that order.
                    // We start with these color at offset 1. We leave the first color as fully transparent.
                    // Index 7 is unused.
                    0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0xff, 0x33, 0x11, 0x00, 0xff, 0x88, 0x77, 0xaa, 0xff,
                    0x66, 0x55, 0x88, 0xff, 0x99, 0x88, 0x77, 0xff, 0xbb, 0xbb, 0x99, 0xff, 0x00, 0x00, 0x00, 0x00,
                    // 16 colors for the blue background gradient of portraits
                    0x00, 0x11, 0x00, 0xff, 0x00, 0x11, 0x11, 0xff, 0x00, 0x11, 0x22, 0xff, 0x00, 0x11, 0x33, 0xff,
                    0x00, 0x11, 0x44, 0xff, 0x00, 0x11, 0x55, 0xff, 0x00, 0x11, 0x66, 0xff, 0x00, 0x11, 0x77, 0xff,
                    0x00, 0x11, 0x88, 0xff, 0x00, 0x11, 0x99, 0xff, 0x00, 0x11, 0xaa, 0xff, 0x00, 0x11, 0xbb, 0xff,
                    0x00, 0x11, 0xcc, 0xff, 0x00, 0x11, 0xdd, 0xff, 0x00, 0x11, 0xee, 0xff, 0x00, 0x11, 0xff, 0xff,
                    // some UI colors (TODO: character with ailment?)
                    0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x66, 0x66, 0x55, 0xff, 0x44, 0x44, 0x33, 0xff,
                    0x22, 0x22, 0x22, 0xff, 0x88, 0x88, 0x77, 0xff, 0xaa, 0xaa, 0x99, 0xff, 0xcc, 0xcc, 0xbb, 0xff
                }
            });

            // Add the 9 intro palettes
            int introPaletteCount = introData == null ? 0 : Math.Min(9, introData.IntroPalettes.Count);
            int p = 0;

            for (; p < introPaletteCount; ++p)
            {
                Palettes.Add(54 + p, introData.IntroPalettes[p]);
            }
            for (; p < 9; ++p)
            {
                Palettes.Add(54 + p, new Graphic
                {
                    Width          = 32,
                    Height         = 1,
                    IndexedGraphic = false,
                    Data           = new byte[32 * 4]
                });
            }

            // Add the 6 outro palettes
            int outroPaletteCount = outroData == null ? 0 : Math.Min(6, outroData.OutroPalettes.Count);

            p = 0;
            for (; p < outroPaletteCount; ++p)
            {
                Palettes.Add(63 + p, outroData.OutroPalettes[p]);
            }
            for (; p < 6; ++p)
            {
                Palettes.Add(63 + p, new Graphic
                {
                    Width          = 32,
                    Height         = 1,
                    IndexedGraphic = false,
                    Data           = new byte[32 * 4]
                });
            }

            foreach (var type in Enum.GetValues <GraphicType>())
            {
                if (type == GraphicType.Cursor)
                {
                    var cursorGraphics = graphics[GraphicType.Cursor] = new List <Graphic>();

                    foreach (var cursor in executableData.Cursors.Entries)
                    {
                        cursorGraphics.Add(cursor.Graphic);
                    }
                }
                else if (type == GraphicType.UIElements)
                {
                    graphics[type] = UIElementProvider.Create();
                    graphics[type].AddRange(executableData.UIGraphics.Entries.Values);
                    graphics[type].AddRange(executableData.Buttons.Entries.Values);
                }
                else if (type == GraphicType.TravelGfx)
                {
                    graphics[type] = gameData.TravelGraphics;
                }
                else if (type == GraphicType.Transports)
                {
                    var reader = gameData.Files["Stationary"].Files[1];
                    reader.Position = 0;
                    graphics[type]  = gameData.StationaryImageInfos.Select(info =>
                    {
                        var graphic = new Graphic();
                        graphicReader.ReadGraphic(graphic, reader, info.Value);
                        return(graphic);
                    }).ToList();
                }
                else if (type == GraphicType.NPC)
                {
                    var npcGraphics = new List <Graphic>(34);
                    var graphicInfo = new GraphicInfo
                    {
                        Width         = 16,
                        Height        = 32,
                        GraphicFormat = GraphicFormat.Palette5Bit,
                        Alpha         = true,
                        PaletteOffset = 0
                    };
                    var graphic = new Graphic();
                    foreach (var file in gameData.Files["NPC_gfx.amb"].Files)
                    {
                        NPCGraphicOffsets.Add(file.Key, npcGraphics.Count);
                        var reader = file.Value;
                        reader.Position = 0;

                        while (reader.Position <= reader.Size - graphicInfo.DataSize)
                        {
                            int numFrames = reader.ReadByte();
                            reader.AlignToWord();
                            var compoundGraphic = new Graphic(16 * numFrames, 32, 0);

                            for (int i = 0; i < numFrames; ++i)
                            {
                                graphicReader.ReadGraphic(graphic, reader, graphicInfo);
                                compoundGraphic.AddOverlay((uint)i * 16, 0, graphic, false);
                            }

                            npcGraphics.Add(compoundGraphic);
                        }
                    }

                    graphics[type] = npcGraphics;
                }
                else if (type == GraphicType.CombatGraphics)
                {
                    var combatGraphics = new List <Graphic>(42);
                    var graphicInfo    = new GraphicInfo
                    {
                        GraphicFormat = GraphicFormat.Palette5Bit,
                        Alpha         = true,
                        PaletteOffset = 0
                    };
                    var reader = gameData.Files["Combat_graphics"].Files[1];
                    reader.Position = 0;

                    foreach (var combatGraphic in CombatGraphics.Info)
                    {
                        var info = combatGraphic.Value;

                        if (combatGraphic.Key == CombatGraphicIndex.BattleFieldIcons)
                        {
                            var battleFieldIcons = new List <Graphic>(35);
                            var iconGraphicInfo  = new GraphicInfo
                            {
                                Width         = 16,
                                Height        = 14,
                                GraphicFormat = GraphicFormat.Palette5Bit,
                                Alpha         = true,
                                PaletteOffset = 0
                            };

                            for (int i = 0; i < 35; ++i)
                            {
                                var graphic = new Graphic();
                                graphicReader.ReadGraphic(graphic, reader, iconGraphicInfo);
                                battleFieldIcons.Add(graphic);
                            }

                            graphics[GraphicType.BattleFieldIcons] = battleFieldIcons;
                        }
                        else
                        {
                            var graphic         = new Graphic();
                            var compoundGraphic = new Graphic((int)info.FrameCount * info.GraphicInfo.Width, info.GraphicInfo.Height, 0);

                            for (int i = 0; i < info.FrameCount; ++i)
                            {
                                graphicReader.ReadGraphic(graphic, reader, info.GraphicInfo);
                                compoundGraphic.AddOverlay((uint)(i * info.GraphicInfo.Width), 0, graphic, false);
                            }

                            combatGraphics.Add(compoundGraphic);
                        }
                    }

                    graphics[type] = combatGraphics;
                }
                else if (type == GraphicType.BattleFieldIcons)
                {
                    // Do nothing. This is filled when processing GraphicType.CombatGraphics.
                }
                else if (type == GraphicType.RiddlemouthGraphics)
                {
                    var riddlemouthGraphics = new List <Graphic>(4 + 7);
                    var reader = gameData.Files["Riddlemouth_graphics"].Files[1];
                    reader.Position = 0;
                    // 4 eye frames
                    ReadAndAddGraphics(4, 48, 9);
                    // 7 mouth frames
                    ReadAndAddGraphics(7, 48, 15);
                    void ReadAndAddGraphics(int frames, int width, int height)
                    {
                        var graphicInfo = new GraphicInfo
                        {
                            Width         = width,
                            Height        = height,
                            GraphicFormat = GraphicFormat.Palette3Bit,
                            Alpha         = false,
                            PaletteOffset = 24
                        };
                        var graphic         = new Graphic();
                        var compoundGraphic = new Graphic(frames * width, height, 0);

                        for (int f = 0; f < frames; ++f)
                        {
                            graphicReader.ReadGraphic(graphic, reader, graphicInfo);
                            compoundGraphic.AddOverlay((uint)(f * width), 0, graphic, false);
                        }
                        riddlemouthGraphics.Add(compoundGraphic);
                    }

                    graphics[type] = riddlemouthGraphics;
                }
                else if (type == GraphicType.AutomapGraphics)
                {
                    var automapGraphics = new List <Graphic>(43);
                    var reader          = gameData.Files["Automap_graphics"].Files[1];
                    reader.Position = 0x100; // TODO: maybe decode the bytes before that later

                    void ReadAndAddGraphics(int amount, int width, int height, GraphicFormat graphicFormat,
                                            int frames = 1, bool alpha = false)
                    {
                        var graphicInfo = new GraphicInfo
                        {
                            Width         = width,
                            Height        = height,
                            GraphicFormat = graphicFormat,
                            Alpha         = alpha,
                            PaletteOffset = 0
                        };

                        for (int i = 0; i < amount; ++i)
                        {
                            Graphic graphic = new Graphic();
                            if (frames == 1)
                            {
                                graphicReader.ReadGraphic(graphic, reader, graphicInfo);
                            }
                            else
                            {
                                var compoundGraphic = new Graphic(frames * width, height, 0);

                                for (int f = 0; f < frames; ++f)
                                {
                                    graphicReader.ReadGraphic(graphic, reader, graphicInfo);
                                    compoundGraphic.AddOverlay((uint)(f * width), 0, graphic, false);
                                }

                                graphic = compoundGraphic;
                            }
                            automapGraphics.Add(graphic);
                        }
                    }

                    // Map corners
                    ReadAndAddGraphics(4, 32, 32, GraphicFormat.Palette3Bit);
                    // Top map border
                    ReadAndAddGraphics(4, 16, 32, GraphicFormat.Palette3Bit);
                    // Right map border
                    ReadAndAddGraphics(2, 32, 32, GraphicFormat.Palette3Bit);
                    // Bottom map border
                    ReadAndAddGraphics(4, 16, 32, GraphicFormat.Palette3Bit);
                    // Left map border
                    ReadAndAddGraphics(2, 32, 32, GraphicFormat.Palette3Bit);
                    // 10 pin graphics
                    ReadAndAddGraphics(10, 16, 16, GraphicFormat.Palette5Bit, 1, true);
                    // Riddlemouth (4 frames)
                    ReadAndAddGraphics(1, 16, 16, GraphicFormat.Palette5Bit, 4, true);
                    // Teleport (4 frames)
                    ReadAndAddGraphics(1, 16, 16, GraphicFormat.Palette5Bit, 4, true);
                    // Spinner (4 frames)
                    ReadAndAddGraphics(1, 16, 16, GraphicFormat.Palette5Bit, 4, true);
                    // Trap (4 frames)
                    ReadAndAddGraphics(1, 16, 16, GraphicFormat.Palette5Bit, 4, true);
                    // Trapdoor (4 frames)
                    ReadAndAddGraphics(1, 16, 16, GraphicFormat.Palette5Bit, 4, true);
                    // Special (4 frames)
                    ReadAndAddGraphics(1, 16, 16, GraphicFormat.Palette5Bit, 4, true);
                    // Monster (4 frames)
                    ReadAndAddGraphics(1, 16, 16, GraphicFormat.Palette5Bit, 4, true);
                    // Door closed (1 frame)
                    ReadAndAddGraphics(1, 16, 16, GraphicFormat.Palette5Bit, 1, true);
                    // Door open (1 frame)
                    ReadAndAddGraphics(1, 16, 16, GraphicFormat.Palette5Bit, 1, true);
                    // Merchant (1 frame)
                    ReadAndAddGraphics(1, 16, 16, GraphicFormat.Palette5Bit, 1, true);
                    // Inn (1 frame)
                    ReadAndAddGraphics(1, 16, 16, GraphicFormat.Palette5Bit, 1, true);
                    // Chest closed (1 frame)
                    ReadAndAddGraphics(1, 16, 16, GraphicFormat.Palette5Bit, 1, true);
                    // Exit (1 frame)
                    ReadAndAddGraphics(1, 16, 16, GraphicFormat.Palette5Bit, 1, true);
                    // Chest open (1 frame)
                    ReadAndAddGraphics(1, 16, 16, GraphicFormat.Palette5Bit, 1, true);
                    // Pile (1 frame)
                    ReadAndAddGraphics(1, 16, 16, GraphicFormat.Palette5Bit, 1, true);
                    // Person (1 frame)
                    ReadAndAddGraphics(1, 16, 16, GraphicFormat.Palette5Bit, 1, true);
                    // Goto point (7 frames)
                    ReadAndAddGraphics(1, 16, 16, GraphicFormat.Palette5Bit, 7, true);

                    graphics[type] = automapGraphics;
                }
                else
                {
                    LoadGraphics(type);
                }
            }
        }