The GBA.Bitmap stores image data in 1bpp indexed format, with 16-bit colors in its palette
Inheritance: IDisplayable
示例#1
0
 public Background(
     int width, int height,
     GBA.Bitmap image,
     int paletteAmount,
     bool checkRedundantTiles)
     : base(width, height, image, paletteAmount, checkRedundantTiles)
 {
 }
示例#2
0
 public WorldMap_FE6_Large(
     Pointer palette,
     Pointer tiles)
 {
     Pointer[] palettes = GetPointerArray(palette);
     Pointer[] tilesets = GetPointerArray(tiles);
     Graphics = new GBA.Bitmap[4];
     for (int i = 0; i < 4; i++)
     {
         Graphics[i] = new GBA.Bitmap(240, 160,
                                      Core.ReadData(palettes[i], 0),
                                      Core.ReadData(tilesets[i], 0));
         for (int p = 0; p < 256; p++)
         {
             Graphics[i].Colors[p] = Graphics[i].Colors[p].SetAlpha(false);
         }
     }
 }
        void Core_Screen_InsertImage(string filepath)
        {
            BattleScreen screen;

            try
            {
                GBA.Bitmap  image    = new GBA.Bitmap(filepath);
                GBA.Palette palettes = new Palette(
                    filepath.Substring(0, filepath.Length - 4) + " palette.png", 4 * Palette.MAX);

                screen = new BattleScreen(image, Palette.Split(palettes, 4));
            }
            catch (Exception ex)
            {
                Program.ShowError("Could not load the image.", ex);
                return;
            }
            Core_Insert(screen);
        }
        void Core_DrawLayer(GBA.Bitmap result, GBA.Image image, Rectangle region, int offsetX, int offsetY)
        {
            int index;
            int pixel;

            for (int y = 0; y < region.Height; y++)
            {
                for (int x = 0; x < region.Width; x++)
                {
                    index = ((region.X + x) / 2) + ((region.Y + y) * (image.Width / 2));
                    pixel = (x % 2 == 0) ?
                            (image.Bytes[index] & 0x0F) :
                            (image.Bytes[index] & 0xF0) >> 4;
                    if (pixel != 0)
                    {
                        result.SetColor(offsetX + x, offsetY + y, image.Colors[pixel]);
                    }
                }
            }
        }
示例#5
0
        public WorldMap_FE6_Large(GBA.Bitmap image)
        {
            if (image.Width != Width || image.Height != Height)
            {
                throw new Exception("Image given has invalid dimensions. It should be 480x320 pixels.");
            }

            for (int i = image.Colors.Count; i < 256; i++)
            {
                image.Colors.Add(new GBA.Color(0x0000));
            }
            Graphics = new GBA.Bitmap[4];
            for (int i = 0; i < 4; i++)
            {
                Graphics[i] = new GBA.Bitmap(image, new Rectangle(
                                                 ((i & 0x1) == 0) ? 0 : 240,
                                                 ((i & 0x2) == 0) ? 0 : 160,
                                                 240, 160));
            }
        }
示例#6
0
        public Font(GBA.Bitmap image)
        {
            GBA.Color[] colors = new GBA.Color[4]
            {
                image.Colors[0],
                image.Colors[1],
                image.Colors[2],
                image.Colors[3]
            };
            Glyphs = new Glyph[256];
            int x = 1;
            int y = 0;

            for (int i = 1; i < Glyphs.Length; i++)
            {
                Glyphs[i] = new Glyph(new GBA.Bitmap(image,
                                                     new Rectangle(x * 16, y * 16, 16, 16)), colors);

                if (Glyphs[i].IsEmpty())
                {
                    Glyphs[i] = null;
                }

                /*
                 * for (int j = 0; j < i; j++)
                 * {
                 *  if (Glyphs[i].Equals(Glyphs[j]))
                 *      Glyphs[i] = Glyphs[j];
                 * }
                 */
                x++;
                if (x % 16 == 0)
                {
                    x = 0;
                    y++;
                }
            }
        }
        void Core_LoadTitleScreen_FE8(
            Palette bg_palette, Tileset bg_tileset, TSA_Array bg_tsa,
            Palette mg_palette, Tileset mg_tileset, TSA_Array mg_tsa,
            Palette fg_palette, Tileset fg_tileset)
        {
            GBA.Bitmap result;
            Palette    palette = Palette.Empty(256);

            for (int i = 0; i < bg_palette.Count; i++)
            {
                bg_palette[i] = bg_palette[i].SetAlpha(false);
                palette.Set(GBA.Palette.MAX * 15 + i, bg_palette[i]);
            }
            for (int i = 0; i < mg_palette.Count; i++)
            {
                palette.Set(GBA.Palette.MAX * 14 + i, mg_palette[i]);
            }
            for (int i = 0; i < fg_palette.Count; i++)
            {
                palette.Set(i, fg_palette[i]);
            }
            result        = new GBA.Bitmap(GBA.Screen.WIDTH, GBA.Screen.HEIGHT);
            result.Colors = palette;

            if (BG_CheckBox.Checked)
            {
                TSA_Image bg = new TSA_Image(bg_palette, bg_tileset, bg_tsa);
                for (int y = 0; y < bg.Height; y++)
                {
                    for (int x = 0; x < bg.Width; x++)
                    {
                        if (bg[x, y] != 0)
                        {
                            result[x, y] = GBA.Palette.MAX * 15 + bg[x, y];
                        }
                    }
                }
            }
            if (MG_CheckBox.Checked)
            {
                TSA_Image mg = new TSA_Image(mg_palette, mg_tileset, mg_tsa);
                for (int y = 0; y < mg.Height; y++)
                {
                    for (int x = 0; x < mg.Width; x++)
                    {
                        if (mg[x, y] != 0)
                        {
                            result[x, y] = GBA.Palette.MAX * 14 + mg[x, y];
                        }
                    }
                }
            }
            if (FG_CheckBox.Checked)
            {
                Palette[] palettes = Palette.Split(fg_palette, 8);
                GBA.Image fg;
                if (Core.CurrentROM.Version == GameVersion.JAP)
                {
                    // large 'FIRE EMBLEM' title logo
                    fg = fg_tileset.ToImage(32, 32, palettes[2].ToBytes(false));
                    Core_DrawLayer(result, fg, new Rectangle(0, 48, 240, 48), 0, 44);   // shadow
                    Core_DrawLayer(result, fg, new Rectangle(0, 0, 240, 48), 0, 39);    // logo
                    Core_DrawLayer(result, fg, new Rectangle(240, 0, 16, 16), 216, 39); // TM
                    // small 'FIRE EMBLEM' overhead
                    fg.Colors = palettes[1];
                    Core_DrawLayer(result, fg, new Rectangle(128, 104, 120, 16), 60, 26);
                    // 'THE SACRED STONES' subtitle/scroll thingy
                    fg.Colors = palettes[3];
                    Core_DrawLayer(result, fg, new Rectangle(0, 104, 128, 32), 56, 87);
                    // 'Press START'
                    fg.Colors = palettes[0];
                    Core_DrawLayer(result, fg, new Rectangle(128, 120, 80, 16), 80, 124);
                    // Nintendo & IS copyrights
                    fg.Colors = palettes[1];
                    Core_DrawLayer(result, fg, new Rectangle(0, 96, 240, 8), 16, 148);
                }
                else
                {
                    // large 'FIRE EMBLEM' title logo
                    fg = fg_tileset.ToImage(32, 32, palettes[2].ToBytes(false));
                    Core_DrawLayer(result, fg, new Rectangle(0, 32, 240, 32), 4, 53);   // shadow
                    Core_DrawLayer(result, fg, new Rectangle(0, 0, 240, 32), 4, 48);    // logo
                    Core_DrawLayer(result, fg, new Rectangle(240, 0, 16, 16), 220, 41); // TM
                    // 'THE SACRED STONES' subtitle/scroll thingy
                    fg.Colors = palettes[3];
                    Core_DrawLayer(result, fg, new Rectangle(0, 72, 208, 32), 16, 85);
                    // 'Press START'
                    fg.Colors = palettes[0];
                    Core_DrawLayer(result, fg, new Rectangle(208, 72, 48, 16), 72, 124);
                    Core_DrawLayer(result, fg, new Rectangle(208, 88, 48, 16), 120, 124);
                    // Nintendo & IS copyrights
                    fg.Colors = palettes[1];
                    Core_DrawLayer(result, fg, new Rectangle(0, 64, 240, 8), 4, 148);
                }
            }
            Current        = result;
            CurrentPalette = palette;
        }
        void Core_LoadTitleScreen_FE7(
            Palette bg_palette, Tileset bg_tileset,
            Palette mg_palette, Tileset mg_tileset, TSA_Array mg_tsa,
            Palette fg_palette, Tileset fg_tileset)
        {
            GBA.Bitmap result;
            Palette    palette = Palette.Empty(256);

            for (int i = 0; i < bg_palette.Count; i++)
            {
                palette.Set(GBA.Palette.MAX * 15 + i, bg_palette[i]);
            }
            for (int i = 0; i < mg_palette.Count; i++)
            {
                palette.Set(GBA.Palette.MAX * 14 + i, mg_palette[i]);
            }
            for (int i = 0; i < fg_palette.Count; i++)
            {
                palette.Set(i, fg_palette[i]);
            }
            result        = new GBA.Bitmap(GBA.Screen.WIDTH, GBA.Screen.HEIGHT);
            result.Colors = palette;

            if (BG_CheckBox.Checked)
            {
                GBA.Image bg = bg_tileset.ToImage(GBA.Screen.W_TILES, GBA.Screen.H_TILES + 1, bg_palette.ToBytes(false));
                for (int y = 0; y < GBA.Screen.HEIGHT; y++)
                {
                    for (int x = 0; x < GBA.Screen.WIDTH; x++)
                    {
                        if (x < 8 && y < 8)
                        {
                            result[x, y] = GBA.Palette.MAX * 15 + bg[x, GBA.Screen.HEIGHT + y];
                        }
                        else
                        {
                            result[x, y] = GBA.Palette.MAX * 15 + bg[x, y];
                        }
                    }
                }
            }
            if (MG_CheckBox.Checked)
            {
                TSA_Image mg = new TSA_Image(mg_palette, mg_tileset, mg_tsa);
                for (int y = 0; y < mg.Height; y++)
                {
                    for (int x = 0; x < mg.Width; x++)
                    {
                        if (mg[x, y] != 0)
                        {
                            result[x, 8 + y] = GBA.Palette.MAX * 14 + mg[x, y];
                        }
                    }
                }
            }
            if (FG_CheckBox.Checked)
            {
                bool      jap      = (Core.CurrentROM.Version == GameVersion.JAP);
                bool      eur      = (Core.CurrentROM.Version == GameVersion.EUR);
                Palette[] palettes = Palette.Split(fg_palette, 8);
                GBA.Image fg;
                // durandal sword
                fg = fg_tileset.ToImage(32, 32, palettes[0].ToBytes(false));
                Core_DrawLayer(result, fg, new Rectangle(0, 0, 192, 112), 32, 16);
                // large 'FIRE EMBLEM' title
                fg.Colors = palettes[4];
                Core_DrawLayer(result, fg, new Rectangle(0, GBA.Screen.HEIGHT, GBA.Screen.WIDTH, 48), 2, jap ? 52 : 54);
                Core_DrawLayer(result, fg, new Rectangle(0, GBA.Screen.HEIGHT - 48, GBA.Screen.WIDTH, 48), 0, jap ? 48 : 52);
                // Nintendo & IS copyrights
                fg.Colors = palettes[2];
                Core_DrawLayer(result, fg, new Rectangle(0, GBA.Screen.WIDTH - 16, GBA.Screen.HEIGHT - 16, 8), eur ?   8 : 16, GBA.Screen.HEIGHT - 16);
                Core_DrawLayer(result, fg, new Rectangle(0, GBA.Screen.WIDTH - 8, GBA.Screen.HEIGHT - 64, 8), eur ? 136 : GBA.Screen.HEIGHT, GBA.Screen.HEIGHT - 16);
                // 'Press Start'
                fg.Colors = palettes[1];
                Core_DrawLayer(result, fg, new Rectangle(128, 208, 96, 16), jap ? 80 : 72, 120);
                if (jap)
                {   // japanese subtitle
                    fg.Colors = palettes[3];
                    Core_DrawLayer(result, fg, new Rectangle(144, 224, 112, 32), 64, 96);
                    // japanese 'FIRE EMBLEM' overhead
                    fg.Colors = palettes[2];
                    Core_DrawLayer(result, fg, new Rectangle(0, 208, 128, 16), 56, 40);
                }
            }
            Current        = result;
            CurrentPalette = palette;
        }
        void Core_LoadTitleScreen_FE6(
            Palette mg_palette, Tileset mg_tileset,
            Tileset fg_tileset, TSA_Array mg_tsa,
            Palette bg_palette, Tileset bg_tileset)
        {
            GBA.Bitmap result;
            Palette    palette = Palette.Empty(256);

            for (int i = 0; i < mg_palette.Count; i++)
            {
                palette.Set(i, mg_palette[i]);
            }
            for (int i = 0; i < bg_palette.Count; i++)
            {
                bg_palette[i] = bg_palette[i].SetAlpha(false);
                palette.Set(GBA.Palette.MAX * 15 + i, bg_palette[i]);
            }
            result        = new GBA.Bitmap(GBA.Screen.WIDTH, GBA.Screen.HEIGHT);
            result.Colors = palette;

            if (BG_CheckBox.Checked)
            {
                GBA.Image bg = bg_tileset.ToImage(GBA.Screen.W_TILES + 2, GBA.Screen.H_TILES, bg_palette.ToBytes(false));
                for (int y = 0; y < GBA.Screen.HEIGHT; y++)
                {
                    for (int x = 0; x < GBA.Screen.WIDTH; x++)
                    {
                        result[x, y] = GBA.Palette.MAX * 15 + bg[x, y];
                    }
                }
            }
            if (MG_CheckBox.Checked)
            {
                TSA_Image mg = new TSA_Image(mg_palette, mg_tileset, mg_tsa);
                for (int y = 0; y < GBA.Screen.HEIGHT; y++)
                {
                    for (int x = 0; x < GBA.Screen.WIDTH; x++)
                    {
                        if (mg.GetColor(x, y).Value != 0)
                        {
                            result[x, y] = mg[x, y];
                        }
                    }
                }
            }
            if (FG_CheckBox.Checked)
            {
                Palette[] palettes = Palette.Split(mg_palette, 8);
                GBA.Image fg;
                // large japanese 'FIRE EMBLEM' title
                fg = mg_tileset.ToImage(32, 25, palettes[4].ToBytes(false));
                Core_DrawLayer(result, fg, new Rectangle(0, 152, GBA.Screen.WIDTH, 48), 0, 48);
                Core_DrawLayer(result, fg, new Rectangle(0, 104, GBA.Screen.WIDTH, 48), 0, 40);
                // small english 'FIRE EMBLEM'
                fg = fg_tileset.ToImage(32, 32, palettes[2].ToBytes(false));
                Core_DrawLayer(result, fg, new Rectangle(0, 0, 128, 16), 99, 27);
                // Nintendo & IS copyrights
                Core_DrawLayer(result, fg, new Rectangle(0, 48, 208, 8), 16, 152);
                // japanese subtitle scroll thingy
                fg.Colors = palettes[3];
                Core_DrawLayer(result, fg, new Rectangle(128, 16, 120, 32), 64, 85);
                // 'Press Start'
                fg.Colors = palettes[1];
                Core_DrawLayer(result, fg, new Rectangle(128, 0, 80, 16), 80, 120);
            }
            Current        = result;
            CurrentPalette = palette;
        }
示例#10
0
        void Core_InsertImage(string filepath)
        {
            IDisplayable image;

            try
            {
                Palette palette = Core.FindPaletteFile(filepath);

                if (TSA_Label.Checked && TSA_PointerBox.Value != new Pointer())
                {
                    int width = TSA_FlipRows_CheckBox.Checked ?
                                ((TSA_Image)Image_ImageBox.Display).Tiling.Width :
                                (int)Width_NumBox.Value;
                    int height = TSA_FlipRows_CheckBox.Checked ?
                                 ((TSA_Image)Image_ImageBox.Display).Tiling.Height :
                                 (int)Height_NumBox.Value;

                    if (palette == null)
                    {
                        image = new TSA_Image(
                            width, height,
                            new GBA.Bitmap(filepath),
                            Palette.MAX,
                            true);
                    }
                    else
                    {
                        image = new TSA_Image(
                            width, height,
                            new GBA.Bitmap(filepath),
                            palette,
                            Palette.MAX,
                            true);
                    }
                }
                else if (Tileset_8bpp_RadioButton.Checked)
                {
                    image = new GBA.Bitmap(filepath, palette);
                }
                else
                {
                    image = new GBA.Image(filepath, palette);
                }
            }
            catch (Exception ex)
            {
                Program.ShowError("Could not load image file.", ex);
                Core_Update();
                return;
            }

            if (image is GBA.TSA_Image)
            {
                Core_Insert(
                    Palette.Merge(((TSA_Image)image).Palettes),
                    ((TSA_Image)image).Graphics.ToBytes(false),
                    ((TSA_Image)image).Tiling);
                return;
            }
            if (image is GBA.Bitmap)
            {
                Core_Insert(
                    ((Bitmap)image).Colors,
                    ((Bitmap)image).ToBytes());
                return;
            }
            if (image is GBA.Image)
            {
                Core_Insert(
                    ((Image)image).Colors,
                    new Tileset((Image)image).ToBytes(false));
                return;
            }
            Program.ShowError("Image couldn't be inserted because of an internal error.");
        }
示例#11
0
        void Core_LoadMap_Units(GBA.Bitmap result)
        {
            try
            {
                Pointer address_mapsprites = Core.GetPointer("Map Sprite Idle Array");
                Pointer address_classes    = Core.GetPointer("Class Array");
                Pointer address;
                byte    palette_index;
                byte    palette_amount = 4;
                address = Core.GetPointer("Map Sprite Palettes");
                byte[][] palettes = new byte[palette_amount][];
                for (int i = 0; i < palette_amount; i++)
                {
                    palettes[i] = Core.ReadData(address + i * Palette.LENGTH, Palette.LENGTH);
                    result.Colors.Add(new Palette(palettes[i]));
                }
                int       class_length = (Core.CurrentROM is FE6 ? 72 : 84);
                GBA.Image image;
                byte      unitclass;
                byte      mapsprite;
                byte      size;
                Tileset   tileset;
                int       offsetX;
                int       offsetY;
                int       index;
                for (int i = 0; i < EventList.Count; i++)
                {
                    if (EventList[i].Command == "UNIT" &&
                        EventList[i].Label != null)
                    {
                        index = UnitEvents_ListBox.Items.IndexOf(EventList[i].Label);
                        if (index == -1)
                        {
                            continue;
                        }
                        else if (!UnitEvents_ListBox.GetItemChecked(index))
                        {
                            continue;
                        }
                        unitclass     = (byte)EventList[i].Arguments[1];
                        mapsprite     = Core.ReadByte(address_classes + 6 + unitclass * class_length);
                        address       = address_mapsprites + mapsprite * 8;
                        size          = Core.ReadByte(address + 2);
                        tileset       = new Tileset(Core.ReadData(Core.ReadPointer(address + 4), 0));
                        palette_index = (byte)(EventList[i].Arguments[3] & 6);
                        if (palette_index > 2)
                        {
                            palette_index -= 3;
                        }
                        switch (size)
                        {
                        case 0x00: image = tileset.ToImage(2, 2, palettes[palette_index]); break;

                        case 0x01: image = tileset.ToImage(2, 4, palettes[palette_index]); break;

                        case 0x02: image = tileset.ToImage(4, 4, palettes[palette_index]); break;

                        default: image = null; break;
                        }
                        if (image != null)
                        {
                            offsetX  = (int)(EventList[i].Arguments[UNIT_argX] * 16);
                            offsetY  = (int)(EventList[i].Arguments[UNIT_argY] * 16);
                            offsetX -= (size == 0x02 ? 8 : 0);
                            offsetY -= (size == 0x00 ? 0 : 16);
                            int pixel;
                            for (int y = 0; y < image.Height; y++)
                            {
                                for (int x = 0; x < image.Width; x++)
                                {
                                    index = (x / 2) + y * (image.Width / 2);
                                    pixel = (x % 2 == 0) ?
                                            (image.Bytes[index] & 0x0F) :
                                            (image.Bytes[index] & 0xF0) >> 4;
                                    if (pixel != 0 &&
                                        offsetX + x >= 0 && offsetX + x < result.Width &&
                                        offsetY + y >= 0 && offsetY + y < result.Height)
                                    {
                                        result.SetColor(offsetX + x, offsetY + y, image.Colors[pixel]);
                                    }
                                }
                            }
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                Program.ShowError("Could not load the units to display on the map.", ex);
            }
        }
示例#12
0
        void Core_LoadMap()
        {
            Pointer address         = Core.GetPointer("Map Data Array");
            Pointer poin_palette    = Core.ReadPointer(address + 4 * (byte)Current["Palette"]);
            Pointer poin_tileset1   = Core.ReadPointer(address + 4 * (byte)Current["Tileset1"]);
            Pointer poin_tileset2   = Core.ReadPointer(address + 4 * (byte)Current["Tileset2"]);
            Pointer poin_tsa        = Core.ReadPointer(address + 4 * (byte)Current["TSA"]);
            Pointer poin_mapdata    = Core.ReadPointer(address + 4 * (byte)Current["Map"]);
            Pointer poin_mapchanges = Core.ReadPointer(address + 4 * (byte)Current["MapChanges"]);

            MapTileset map_tileset;

            try
            {
                map_tileset = new MapTileset(
                    Core.ReadData(poin_palette, Map.PALETTES * Palette.LENGTH),
                    Core.ReadData(poin_tileset1, 0),
                    Core.ReadData(poin_tileset2, 0),
                    Core.ReadData(poin_tsa, 0));
            }
            catch (Exception ex)
            {
                map_tileset = null;
                Program.ShowError("Could not load the the tileset for this chapter.", ex);
            }

            try
            {
                CurrentMap = new Map(map_tileset,
                                     Core.ReadData(poin_mapdata, 0),
                                     poin_mapchanges, false);
            }
            catch (Exception ex)
            {
                CurrentMap = null;
                Program.ShowError("Could not load the map for this chapter.", ex);
            }

            if (CurrentMap.Changes != null)
            {
                MapChanges_ListBox.ItemCheck -= MapChanges_ListBox_ItemCheck;
                if (MapChanges_ListBox.Items.Count > 0)
                {
                    for (int i = 0; i < CurrentMap.ShowChanges.Length; i++)
                    {
                        CurrentMap.ShowChanges[i] = MapChanges_ListBox.GetItemChecked(i);
                    }
                    MapChanges_ListBox.Items.Clear();
                }
                for (int i = 0; i < CurrentMap.Changes.Count; i++)
                {
                    MapChanges_ListBox.Items.Add(
                        "0x" + Util.ByteToHex(CurrentMap.Changes.GetNumber(i)),
                        CurrentMap.ShowChanges[i]);
                }
                MapChanges_ListBox.ItemCheck += MapChanges_ListBox_ItemCheck;
            }

            GBA.Bitmap result = new GBA.Bitmap(CurrentMap);

            if (View_Units.Checked)
            {
                Core_LoadMap_Units(result);
            }

            MapViewBox.Size = new Size(CurrentMap.Width, CurrentMap.Height);
            MapViewBox.Load(result);
        }
示例#13
0
        private void File_Tools_CreateImage_Click(Object sender, EventArgs e)
        {
            GBA.Bitmap idle = null;
            GBA.Bitmap move = null;
            byte       size;

            OpenFileDialog openWindow_idle = new OpenFileDialog();

            openWindow_idle.RestoreDirectory = true;
            openWindow_idle.Multiselect      = false;
            openWindow_idle.FilterIndex      = 1;
            openWindow_idle.Filter           =
                "'IDLE' Map sprite image file (*.png, *.bmp, *.gif)|*.png;*.bmp;*.gif|" +
                "All files (*.*)|*.*";
            if (openWindow_idle.ShowDialog() == DialogResult.OK)
            {
                if (openWindow_idle.FileName.EndsWith(".png", StringComparison.OrdinalIgnoreCase) ||
                    openWindow_idle.FileName.EndsWith(".bmp", StringComparison.OrdinalIgnoreCase) ||
                    openWindow_idle.FileName.EndsWith(".gif", StringComparison.OrdinalIgnoreCase))
                {
                    try
                    {
                        idle = new GBA.Bitmap(openWindow_idle.FileName, CurrentPalette);
                    }
                    catch (Exception ex)
                    {
                        Program.ShowError("Could not read bitmap for map sprite 'idle'.", ex);
                        return;
                    }
                    if (idle.Width == 16 && idle.Height == 16 * 3)
                    {
                        size = 0x00;
                    }
                    else if (idle.Width == 16 && idle.Height == 32 * 3)
                    {
                        size = 0x01;
                    }
                    else if (idle.Width == 32 && idle.Height == 32 * 3)
                    {
                        size = 0x02;
                    }
                    else
                    {
                        Program.ShowError("Invalid IDLE Map sprite image file, size should be either 16x48, 16x96, or 32x96 pixels");
                        return;
                    }
                }
                else
                {
                    Program.ShowError("File chosen has invalid extension.\r\n" + openWindow_idle.FileName);
                    return;
                }
            }
            else
            {
                return;
            }

            OpenFileDialog openWindow_move = new OpenFileDialog();

            openWindow_move.RestoreDirectory = true;
            openWindow_move.Multiselect      = false;
            openWindow_move.FilterIndex      = 1;
            openWindow_move.Filter           =
                "'MOVE' Map sprite image file (*.png, *.bmp, *.gif)|*.png;*.bmp;*.gif|" +
                "'MOVE' Map sprite image data (.move.chr)|*.chr|" +
                "All files (*.*)|*.*";
            if (openWindow_move.ShowDialog() == DialogResult.OK)
            {
                if (openWindow_move.FileName.EndsWith(".png", StringComparison.OrdinalIgnoreCase) ||
                    openWindow_move.FileName.EndsWith(".bmp", StringComparison.OrdinalIgnoreCase) ||
                    openWindow_move.FileName.EndsWith(".gif", StringComparison.OrdinalIgnoreCase))
                {
                    try
                    {
                        move = new GBA.Bitmap(openWindow_move.FileName, CurrentPalette);
                    }
                    catch (Exception ex)
                    {
                        Program.ShowError("Could not read bitmap for map sprite 'move'.", ex);
                        return;
                    }
                    if (move.Width != 32 && move.Height != 480)
                    {
                        Program.ShowError("Invalid MOVE Map sprite image file, size should be 32x480 pixels");
                        return;
                    }
                }
                else if (openWindow_move.FileName.EndsWith(".chr", StringComparison.OrdinalIgnoreCase))
                {
                    // TODO
                    return;
                }
                else
                {
                    Program.ShowError("File chosen has invalid extension.\r\n" + openWindow_move.FileName);
                    return;
                }
            }
            else
            {
                return;
            }

            GBA.Bitmap result = new GBA.Bitmap(
                MapSprite.WIDTH,
                MapSprite.HEIGHT);
            result.Colors = Core.ReadPalette(Core.CurrentROM.Address_MapSpritePalettes(), GBA.Palette.LENGTH * 8);
            result.SetPixels(delegate(int x, int y) { return((byte)move[x, y + 32 * 0]); }, new Rectangle(32, 0, 32, 32 * 4));      // MOVE side
            result.SetPixels(delegate(int x, int y) { return((byte)move[x, y + 32 * 4]); }, new Rectangle(64, 0, 32, 32 * 4));      // MOVE down
            result.SetPixels(delegate(int x, int y) { return((byte)move[x, y + 32 * 8]); }, new Rectangle(96, 0, 32, 32 * 4));      // MOVE up
            result.SetPixels(delegate(int x, int y) { return((byte)move[x, y + 32 * 12]); }, new Rectangle(128, 32, 32, 32 * 3));   // MOVE cursor-hover
            switch (size)
            {
            case 0x00:     // IDLE 16x16
                result.SetPixels(delegate(int x, int y) { return((byte)idle[x, y + 16 * 0]); }, new Rectangle(8, 32 * 1 + 16, 16, 16));
                result.SetPixels(delegate(int x, int y) { return((byte)idle[x, y + 16 * 1]); }, new Rectangle(8, 32 * 2 + 16, 16, 16));
                result.SetPixels(delegate(int x, int y) { return((byte)idle[x, y + 16 * 2]); }, new Rectangle(8, 32 * 3 + 16, 16, 16));
                break;

            case 0x01:     // IDLE 16x32
                result.SetPixels(delegate(int x, int y) { return((byte)idle[x, y]); }, new Rectangle(8, 32, 16, 32 * 3)); break;

            case 0x02:     // IDLE 32x32
                result.SetPixels(delegate(int x, int y) { return((byte)idle[x, y]); }, new Rectangle(0, 32, 32, 32 * 3)); break;

            default: throw new Exception("Invalid map sprite size value recieved.");
            }

            SaveFileDialog saveWindow = new SaveFileDialog();

            saveWindow.RestoreDirectory = true;
            saveWindow.OverwritePrompt  = true;
            saveWindow.CreatePrompt     = false;
            saveWindow.FilterIndex      = 1;
            saveWindow.Filter           =
                "Image file (*.png, *.bmp)|*.png;*.bmp|" +
                "All files (*.*)|*.*";

            if (saveWindow.ShowDialog() == DialogResult.OK)
            {
                if (saveWindow.FileName.EndsWith(".png", StringComparison.OrdinalIgnoreCase) ||
                    saveWindow.FileName.EndsWith(".bmp", StringComparison.OrdinalIgnoreCase))
                {
                    try
                    {
                        Core.SaveImage(saveWindow.FileName.Remove(saveWindow.FileName.Length - 4),
                                       Tile.SIZE * MapSprite.W_TILES,
                                       Tile.SIZE * MapSprite.H_TILES,
                                       Palette.Split(CurrentPalette, 8),
                                       delegate(int x, int y)
                        {
                            return((byte)result[x, y]);
                        });
                    }
                    catch (Exception ex)
                    {
                        Program.ShowError("Could not save image.", ex);
                    }
                    return;
                }
                else
                {
                    Program.ShowError("File chosen has invalid extension.\r\n" + saveWindow.FileName);
                    return;
                }
            }
        }