Exemple #1
0
        bool WriteMapConfig(Undo.UndoData undodata)
        {
            if (this.MapStyle.SelectedIndex < 0)
            {
                return(false);
            }
            uint config_plist    = this.MapEditConf[this.MapStyle.SelectedIndex].config_plist;
            uint chipset_address = MapPointerForm.PlistToOffsetAddr(MapPointerForm.PLIST_TYPE.CONFIG, config_plist);

            byte[] chipsetConfigZ = LZ77.compress(this.ConfigUZ);
            uint   newaddr        = InputFormRef.WriteBinaryData(this, (uint)ChipsetConfigAddress.Value, chipsetConfigZ, InputFormRef.get_data_pos_callback_lz77, undodata);

            if (newaddr == U.NOT_FOUND)
            {
                Program.Undo.Rollback(undodata);
                return(false);
            }
            ChipsetConfigAddress.Value = newaddr;

            //拡張領域に書き込んでいる可能性もあるので plstを更新する.
            bool r = MapPointerForm.Write_Plsit(MapPointerForm.PLIST_TYPE.CONFIG, config_plist, newaddr, undodata);

            if (!r)
            {
                Program.Undo.Rollback(undodata);
                return(false);
            }

            //書き込んだ通知.
            InputFormRef.ShowWriteNotifyAnimation(this, newaddr);
            InputFormRef.WriteButtonToYellow(this.Config_WriteButton, false);
            //マップエディタが開いていれば更新する
            MapEditorForm.UpdateMapStyleIfOpen();
            return(true);
        }
        //マップ領域のベース領域の強制割り当て
        public static uint PreciseMapDataArea(uint mapid)
        {
            MapPointerNewPLISTPopupForm f = (MapPointerNewPLISTPopupForm)InputFormRef.JumpFormLow <MapPointerNewPLISTPopupForm>();

            f.Init(MapPointerForm.PLIST_TYPE.MAP);
            DialogResult dr = f.ShowDialog();

            if (dr != System.Windows.Forms.DialogResult.OK)
            {
                return(0);
            }

            uint plist = f.GetSelectPLIST();

            Undo.UndoData undodata = Program.Undo.NewUndoData("Precise MapDataArea", mapid.ToString("X"));


            //マップ領域を新規に割り当てる
            byte[] data = new byte[2 + (15 * 10)];
            data[0] = 15;
            data[1] = 10;

            data = LZ77.compress(data);

            MapSettingForm.PLists plists = MapSettingForm.GetMapPListsWhereMapID(mapid);
            uint map_addr = MapPointerForm.PlistToOffsetAddr(MapPointerForm.PLIST_TYPE.MAP, plists.mappointer_plist);

            if (U.isSafetyOffset(map_addr))
            {//既存マップがあればコピーする.
                uint length = LZ77.getCompressedSize(Program.ROM.Data, map_addr);
                data = Program.ROM.getBinaryData(map_addr, length);
            }

            uint write_addr = InputFormRef.AppendBinaryData(data, undodata);

            if (write_addr == U.NOT_FOUND)
            {
                Program.Undo.Rollback(undodata);
                return(0);
            }
            bool r = MapPointerForm.Write_Plsit(MapPointerForm.PLIST_TYPE.MAP, plist, write_addr, undodata);

            if (!r)
            {
                Program.Undo.Rollback(undodata);
                return(0);
            }

            Program.Undo.Push(undodata);

            return(plist);
        }
        //OBJECTの割り当て
        public static uint PreciseObjectArea(uint mapid)
        {
            MapPointerNewPLISTPopupForm f = (MapPointerNewPLISTPopupForm)InputFormRef.JumpFormLow <MapPointerNewPLISTPopupForm>();

            f.Init(MapPointerForm.PLIST_TYPE.OBJECT);
            DialogResult dr = f.ShowDialog();

            if (dr != System.Windows.Forms.DialogResult.OK)
            {
                return(0);
            }

            uint plist = f.GetSelectPLIST();

            Undo.UndoData undodata = Program.Undo.NewUndoData("Precise ObjectArea", mapid.ToString("X"));

            //OBJECT領域を新規に割り当てる.
            MapSettingForm.PLists plists = MapSettingForm.GetMapPListsWhereMapID(mapid);
            Bitmap bmp;

            if (plists.obj_plist >= 0x100)
            {//2つのplistが必要だからコピーできない
                bmp = ImageUtil.Blank(32 * 8, 32 * 8);
            }
            else
            {
                bmp = DrawMapChipOnly(plists.obj_plist, plists.palette_plist, null);
            }

            byte[] data = ImageUtil.ImageToByte16Tile(bmp, bmp.Width, bmp.Height);
            data = LZ77.compress(data);

            uint write_addr = InputFormRef.AppendBinaryData(data, undodata);

            if (write_addr == U.NOT_FOUND)
            {
                Program.Undo.Rollback(undodata);
                return(0);
            }
            bool r = MapPointerForm.Write_Plsit(MapPointerForm.PLIST_TYPE.OBJECT, plist, write_addr, undodata);

            if (!r)
            {
                Program.Undo.Rollback(undodata);
                return(0);
            }

            Program.Undo.Push(undodata);

            return(plist);
        }
Exemple #4
0
        private void CompressFireButton_Click(object sender, EventArgs e)
        {
            if (CompressSRCFilename.Text == "" || CompressDESTFilename.Text == "")
            {
                return;
            }

            byte[] src  = File.ReadAllBytes(CompressSRCFilename.Text);
            byte[] data = LZ77.compress(src);

            U.WriteAllBytes(CompressDESTFilename.Text, data);

            //エクスプローラで選択しよう
            U.SelectFileByExplorer(CompressDESTFilename.Text);
        }
Exemple #5
0
        uint RecompressOne(InputFormRef.AutoPleaseWait wait, Address a, Undo.UndoData undodata)
        {
            if (!Address.IsLZ77(a.DataType))
            {//念のためlz77圧縮の確認
                return(0);
            }
            if (!U.isPadding4(a.Addr))
            {//4バイトパディングされていないデータはありえない
                return(0);
            }

            byte[] unzipData = LZ77.decompress(Program.ROM.Data, a.Addr);
            if (unzipData.Length <= 0)
            {
                return(0);
            }
            uint uncompressSize = LZ77.getUncompressSize(Program.ROM.Data, a.Addr);

            if (unzipData.Length != uncompressSize)
            {
                return(0);
            }

            byte[] lz77Data = LZ77.compress(unzipData);
            if (lz77Data.Length >= a.Length)
            {//無意味なのでやらない
                return(0);
            }
            uint diff = (uint)(a.Length - lz77Data.Length);

            if (diff <= 3)
            {//無意味なのでやらない
                return(0);
            }
            //書き込み
            Program.ROM.write_fill(a.Addr, a.Length, 0, undodata);
            Program.ROM.write_range(a.Addr, lz77Data, undodata);
            wait.DoEvents(R._("recompress lz77 {0}", U.To0xHexString(a.Addr)));

            return(diff);
        }
        void WriteLZ77Bin(byte[] bin, uint addr, uint datasize, string debugInfo)
        {
            byte[] newbin = LZ77.compress(bin);

            //領域の確保
            uint writeaddr = 0;

            if (!isVanilaExtrendsROMArea(addr + datasize) &&
                datasize >= newbin.Length)
            {//非拡張領域
                //そのまま書き換えられる
                writeaddr = addr;
            }
            else
            {//リポイントが必要
                writeaddr = Alloc((uint)newbin.Length, addr);
            }
            //データの書き込み
            U.write_range(this.WriteROMData32MB, writeaddr, newbin);
            ResolvedPointer(U.toPointer(addr), U.toPointer(writeaddr), debugInfo);
        }
Exemple #7
0
        public static string Import(string filename, uint anime_pointer)
        {
            string basename = Path.GetFileNameWithoutExtension(filename) + "_";
            string basedir  = Path.GetDirectoryName(filename);

            //同じアニメを何度も入力しないように記録する.
            List <anime> anime_list = new List <anime>();
            List <byte>  frames     = new List <byte>();

            string[] lines = File.ReadAllLines(filename);

            uint      sound_id  = 0x3d1;
            AnimeType animeType = AnimeType.None;

            for (uint lineCount = 0; lineCount < lines.Length; lineCount++)
            {
                string line = lines[lineCount];
                if (U.IsComment(line) || U.OtherLangLine(line))
                {
                    continue;
                }
                line = U.ClipComment(line);
                if (line.Length <= 0)
                {
                    continue;
                }
                InputFormRef.DoEvents(null, "Line:" + lineCount);

                line = line.Replace("\t", " ");
                string[] sp      = line.Split(new string[] { " " }, StringSplitOptions.RemoveEmptyEntries);
                string   command = sp[0];
                if (command.Length <= 0)
                {
                    continue;
                }
                if (command[0] == 'S')
                {
                    sound_id = U.atoh(command.Substring(1));
                    continue;
                }
                if (command[0] == 'D')
                {
                    animeType = AnimeType.D;
                    continue;
                }
                if (!(U.isNumString(command) && sp.Length >= 2))
                {
                    continue;
                }
                if (sp.Length <= 1)
                {
                    Debug.Assert(false);
                    continue;
                }
                uint   wait  = U.atoi(command);
                string image = sp[1];

                uint id = FindImage(anime_list, image);
                if (id == U.NOT_FOUND)
                {
                    id = (uint)anime_list.Count;

                    string fullfilename = Path.Combine(basedir, image);
                    Bitmap bitmap       = ImageUtil.OpenBitmap(fullfilename);
                    if (bitmap == null)
                    {
                        return(R.Error("ファイル名が見つかりませんでした。\r\nFile: {0} line:{1}\r\n\r\nエラー内容:\r\n{2}", filename, lineCount, line));
                    }
                    if (bitmap.Width != SCREEN_WIDTH || bitmap.Height != SCREEN_HEIGHT)
                    {
                        bitmap = ImageUtil.Copy(bitmap, 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT);
                    }

                    anime  a     = new anime();
                    string error = ImageUtil.ImageToBytePackedTSA(bitmap, SCREEN_WIDTH, SCREEN_HEIGHT, 0, out a.image, out a.tsa);
                    if (error != "")
                    {
                        return(R.Error("画像をインポートできません。\r\nFile: {0} line:{1}\r\n\r\nエラー内容:\r\n{2}", filename, lineCount, error));
                    }
                    a.image    = LZ77.compress(a.image);
                    a.tsa      = LZ77.compress(a.tsa);
                    a.pal      = ImageUtil.ImageToPalette(bitmap, 1);
                    a.filename = image;
                    anime_list.Add(a);
                }

                U.append_u16(frames, id);
                U.append_u16(frames, wait);
            }
            //term
            U.append_u16(frames, 0xFFFF);
            U.append_u16(frames, 0xFFFF);

            anime_pointer = U.toOffset(anime_pointer);
            if (!U.isSafetyOffset(anime_pointer))
            {
                return(R._("アドレスが無効です"));
            }
            uint anime_address = Program.ROM.p32(anime_pointer);

            List <Address> recycle = new List <Address>();

            RecycleOldAnime(ref recycle, basename, false, anime_address);
            RecycleAddress ra = new RecycleAddress(recycle);

            Undo.UndoData undodata = Program.Undo.NewUndoData("ImageUtilSkillSystemsAnimeCreator.Import");

            List <byte> image_list = new List <byte>();
            List <byte> tsa_list   = new List <byte>();
            List <byte> pal_list   = new List <byte>();

            for (int i = 0; i < anime_list.Count; i++)
            {
                uint p;
                p = ra.Write(anime_list[i].image, undodata);
                U.append_u32(image_list, U.toPointer(p));

                p = ra.Write(anime_list[i].tsa, undodata);
                U.append_u32(tsa_list, U.toPointer(p));

                p = ra.Write(anime_list[i].pal, undodata);
                U.append_u32(pal_list, U.toPointer(p));
            }

            List <byte> mainData = new List <byte>();

            if (Program.ROM.RomInfo.is_multibyte())
            {//FE8J
             //FE8Jには、スキルごとにプログラムは存在しない.
            }
            else
            {//FE8U
                //信じられないが、スキルアニメ毎にプログラムコードが設定される.
                if (animeType == AnimeType.D)
                {
                    string prog = Path.Combine(Program.BaseDirectory, "config", "patch2", "FE8U", "skill", "skillanimtemplate_defender_2017_01_24.dmp");
                    mainData.AddRange(File.ReadAllBytes(prog));
                }
                else
                {
                    string prog = Path.Combine(Program.BaseDirectory, "config", "patch2", "FE8U", "skill", "skillanimtemplate_2016_11_04.dmp");
                    mainData.AddRange(File.ReadAllBytes(prog));
                }
            }

            //プログラムの下にデータがある.
            {
                uint p;
                p = ra.Write(frames.ToArray(), undodata);
                U.append_u32(mainData, U.toPointer(p));

                p = ra.Write(tsa_list.ToArray(), undodata);
                U.append_u32(mainData, U.toPointer(p));

                p = ra.Write(image_list.ToArray(), undodata);
                U.append_u32(mainData, U.toPointer(p));

                p = ra.Write(pal_list.ToArray(), undodata);
                U.append_u32(mainData, U.toPointer(p));

                U.append_u32(mainData, sound_id);
            }

            //アニメポインタの書き換え.
            ra.WriteAndWritePointer(anime_pointer, mainData.ToArray(), undodata);

            Program.Undo.Push(undodata);
            return("");
        }
        static ImageUtilOAM.animedata ImportBGImageToData(string imagefilename
                                                          , string basedir
                                                          , Dictionary <string, ImageUtilOAM.animedata> animeDic
                                                          , List <ImageUtilOAM.image_data> imagesData
                                                          , out string errormessage
                                                          )
        {
            string key = "BG" + imagefilename;

            ImageUtilOAM.animedata magic_animedata;
            if (animeDic.ContainsKey(key))
            {
                errormessage    = "";
                magic_animedata = animeDic[key];
                return(magic_animedata);
            }

            string hash = ImageUtil.HashBitmap(imagefilename, basedir);

            magic_animedata = ImageUtilOAM.FindHash(hash, animeDic);
            if (magic_animedata != null)
            {
                errormessage = "";
                return(magic_animedata);
            }

            magic_animedata = new ImageUtilOAM.animedata();
            string bgfilename = ImageUtilMagicFEditor.GetFullPath(imagefilename, basedir);
            Bitmap loadbitmap = ImageUtil.OpenBitmap(bgfilename, null, out errormessage);

            if (loadbitmap == null)
            {
                return(null);
            }

//            int width = ImageUtilMagicFEditor.SRC_BG_SEAT_TILE_WIDTH * 8;
//            int height = ImageUtilMagicFEditor.SRC_BG_SEAT_TILE_HEIGHT * 8;
            int width  = 240;
            int height = 160;

            if (loadbitmap.Width < width || loadbitmap.Height < height)
            {
                if ((loadbitmap.Width >= 240 && loadbitmap.Width <= 264) &&
                    (loadbitmap.Height >= 64 && loadbitmap.Height < 160))
                {
                    height = 64;
                    //FEditor Magic
                    Log.Notify("これはFEditorの小さいBG形式です。");
                }
                else if ((loadbitmap.Width >= 240 && loadbitmap.Width <= 264) &&
                         loadbitmap.Height == 160)
                {//CSA Creator
                }
                else
                {
                    errormessage = R.Error("画像サイズが正しくありません。\r\n{4}\r\nWidth:{2} Height:{3} でなければなりません。\r\n\r\n選択された画像のサイズ Width:{0} Height:{1}", loadbitmap.Width, loadbitmap.Height, width, height, imagefilename);
                    loadbitmap.Dispose();
                    return(null);
                }
            }

            Bitmap savebitmap = ImageUtil.Copy(loadbitmap, 0, 0, width, height);

            byte[] image; //画像
            byte[] tsa;   //TSA
            string error_string = ImageUtil.ImageToBytePackedTSA(savebitmap, savebitmap.Width, savebitmap.Height, 0, out image, out tsa);

            if (error_string != "")
            {
                errormessage = error_string;
                loadbitmap.Dispose();
                return(null);
            }

            //画像の高さを記録. BGは、FEditor=64   Scale Creator=160 と、違う.
            magic_animedata.height = height;
            //ハッシュ値
            magic_animedata.imageHash = hash;

            //画像
            magic_animedata.image_pointer = (uint)imagesData.Count;
            ImageUtilOAM.image_data image_data = new ImageUtilOAM.image_data();
            image_data.data = image;
            image_data.data = LZ77.compress(image_data.data);
            imagesData.Add(image_data);

            //パレット
            magic_animedata.palette_pointer = (uint)imagesData.Count;
            ImageUtilOAM.image_data palette_data = new ImageUtilOAM.image_data();
            palette_data.data = ImageUtil.ImageToPalette(savebitmap);
            imagesData.Add(palette_data);

            //TSA
            magic_animedata.tsa_pointer = (uint)imagesData.Count;
            ImageUtilOAM.image_data tsa_data = new ImageUtilOAM.image_data();
            tsa_data.data = tsa;
            tsa_data.data = LZ77.compress(tsa_data.data);
            imagesData.Add(tsa_data);


            animeDic[key] = magic_animedata;
            errormessage  = "";
            loadbitmap.Dispose();
            return(magic_animedata);
        }
Exemple #9
0
        bool WriteMapChipImage(byte[] image, Undo.UndoData undodata)
        {
            if (this.MapStyle.SelectedIndex < 0)
            {
                return(false);
            }
            uint obj_plist  = this.MapEditConf[this.MapStyle.SelectedIndex].obj_plist;
            uint obj2_plist = (obj_plist >> 8) & 0xFF; //FE8にはないが FE7は、 plistを2つ設定できることがある.

            if (obj2_plist > 0)
            {//FE7とかあるフィールド画像分割
                byte[] image1  = U.subrange(image, 0, (uint)(image.Length / 2));
                byte[] image2  = U.subrange(image, (uint)(image.Length / 2), (uint)image.Length);
                byte[] image1Z = LZ77.compress(image1);
                byte[] image2Z = LZ77.compress(image2);
                uint   newaddr = InputFormRef.WriteBinaryData(this, (uint)ObjAddress.Value, image1Z, InputFormRef.get_data_pos_callback_lz77, undodata);
                if (newaddr == U.NOT_FOUND)
                {
                    Program.Undo.Rollback(undodata);
                    return(false);
                }

                ObjAddress.Value = newaddr;
                //拡張領域に書き込んでいる可能性もあるので plstを更新する.
                MapPointerForm.Write_Plsit(MapPointerForm.PLIST_TYPE.OBJECT, obj_plist, newaddr, undodata);

                //分割されたデータを書き込み
                newaddr = InputFormRef.WriteBinaryData(this, (uint)ObjAddress2.Value, image2Z, InputFormRef.get_data_pos_callback_lz77, undodata);
                if (newaddr == U.NOT_FOUND)
                {
                    Program.Undo.Rollback(undodata);
                    return(false);
                }
                ObjAddress2.Value = newaddr;

                //拡張領域に書き込んでいる可能性もあるので plstを更新する.
                bool r = MapPointerForm.Write_Plsit(MapPointerForm.PLIST_TYPE.OBJECT, obj2_plist, newaddr, undodata);
                if (!r)
                {
                    Program.Undo.Rollback(undodata);
                    return(false);
                }

                //書き込んだ通知.
                InputFormRef.ShowWriteNotifyAnimation(this, newaddr);
            }
            else
            {
                byte[] imageZ  = LZ77.compress(image);
                uint   newaddr = InputFormRef.WriteBinaryData(this, (uint)ObjAddress.Value, imageZ, InputFormRef.get_data_pos_callback_lz77, undodata);
                if (newaddr == U.NOT_FOUND)
                {
                    Program.Undo.Rollback(undodata);
                    return(false);
                }
                ObjAddress.Value = newaddr;

                //拡張領域に書き込んでいる可能性もあるので plstを更新する.
                bool r = MapPointerForm.Write_Plsit(MapPointerForm.PLIST_TYPE.OBJECT, obj_plist, newaddr, undodata);
                if (!r)
                {
                    Program.Undo.Rollback(undodata);
                    return(false);
                }
                //書き込んだ通知.
                InputFormRef.ShowWriteNotifyAnimation(this, newaddr);
            }
            return(true);
        }
Exemple #10
0
        string Import(
            string filename      //読込むファイル名
            )
        {
            string basename = Path.GetFileNameWithoutExtension(filename) + "_";
            string basedir  = Path.GetDirectoryName(filename);

            //同じアニメを何度も入力しないように記録する.
            List <anime> anime_list  = new List <anime>();
            int          imageWidth  = this.ImageWidth * 8;
            int          imageHeight = 8 * 16;
            List <byte>  frames      = new List <byte>();

            string[] lines = File.ReadAllLines(filename);
            for (uint lineCount = 0; lineCount < lines.Length; lineCount++)
            {
                string line = lines[lineCount++];
                if (U.IsComment(line) || U.OtherLangLine(line))
                {
                    continue;
                }
                line = U.ClipComment(line);
                if (line.Length <= 0)
                {
                    continue;
                }
                InputFormRef.DoEvents(null, "Line:" + lineCount);

                line = line.Replace("\t", " ");
                string[] sp      = line.Split(new string[] { " " }, StringSplitOptions.RemoveEmptyEntries);
                string   command = sp[0];
                if (command.Length <= 0)
                {
                    continue;
                }
                if (!(U.isNumString(command) && sp.Length >= 2))
                {
                    continue;
                }
                uint   wait  = U.atoi(command);
                string image = sp[1];

                uint id = FindImage(anime_list, image);
                if (id == U.NOT_FOUND)
                {
                    id = (uint)anime_list.Count;

                    string fullfilename = Path.Combine(basedir, image);
                    Bitmap bitmap       = ImageUtil.OpenBitmap(fullfilename);
                    if (bitmap == null)
                    {
                        return(R.Error("ファイル名が見つかりませんでした。\r\nFile: {0} line:{1}\r\n\r\nエラー内容:\r\n{2}", filename, lineCount, line));
                    }
                    if (bitmap.Width != imageWidth || bitmap.Height != imageHeight)
                    {
                        bitmap = ImageUtil.Copy(bitmap, 0, 0, imageWidth, imageHeight);
                    }

                    anime  a     = new anime();
                    string error = ImageUtil.ImageToBytePackedTSA(bitmap, imageWidth, imageHeight, 0, out a.image, out a.tsa);
                    if (error != "")
                    {
                        return(R.Error("画像をインポートできません。\r\nFile: {0} line:{1}\r\n\r\nエラー内容:\r\n{2}", filename, lineCount, error));
                    }
                    a.image    = LZ77.compress(a.image);
                    a.tsa      = LZ77.compress(a.tsa);
                    a.pal      = ImageUtil.ImageToPalette(bitmap, 1);
                    a.filename = image;
                    anime_list.Add(a);
                }

                U.append_u16(frames, id);
                U.append_u16(frames, wait);
            }
            //term
            U.append_u16(frames, 0xFFFF);
            U.append_u16(frames, 0x0);

            if (anime_list.Count <= 0)
            {
                return(R._("書き込むアニメーションがありません"));
            }

            Undo.UndoData undodata = Program.Undo.NewUndoData("");

            List <Address> recycle = new List <FEBuilderGBA.Address>();

            MakeRecycleList(ref recycle, "", false);

            RecycleAddress ra = new RecycleAddress(recycle);

            uint p;

            if (!U.isSafetyOffset(this.FramePointer))
            {//固定フレームのアニメ
                if (this.FramePointer != anime_list.Count)
                {
                    return(R._("このアニメーションは固定アニメーションです。フレームが{0}個必要です。指定されたアニメには{1}のフレームがあり、数が一致していません。", this.FramePointer, anime_list.Count));
                }

                if (this.TSAList.Count == 1 && this.PaletteList.Count >= 2)
                {//パレットアニメ
                    List <byte> pal_list = new List <byte>();
                    for (int i = 0; i < anime_list.Count; i++)
                    {
                        p = ra.Write(anime_list[i].pal, undodata);
                        U.append_u32(pal_list, U.toPointer(p));
                    }

                    ra.WriteAndWritePointer(this.TSAPointer, anime_list[0].tsa, undodata);
                    ra.WriteAndWritePointer(this.ImagePointer, anime_list[0].image, undodata);
                    ra.WriteAndWritePointer(this.PalettePointer, pal_list.ToArray(), undodata);
                }
                else
                {
                    List <byte> image_list = new List <byte>();
                    List <byte> tsa_list   = new List <byte>();
                    List <byte> pal_list   = new List <byte>();
                    for (int i = 0; i < anime_list.Count; i++)
                    {
                        p = ra.Write(anime_list[i].image, undodata);
                        U.append_u32(image_list, U.toPointer(p));

                        p = ra.Write(anime_list[i].tsa, undodata);
                        U.append_u32(tsa_list, U.toPointer(p));

                        p = ra.Write(anime_list[i].pal, undodata);
                        U.append_u32(pal_list, U.toPointer(p));
                    }

                    ra.WriteAndWritePointer(this.TSAPointer, tsa_list.ToArray(), undodata);
                    ra.WriteAndWritePointer(this.ImagePointer, image_list.ToArray(), undodata);
                    ra.WriteAndWritePointer(this.PalettePointer, pal_list.ToArray(), undodata);
                }
            }
            else
            {     //フレームを利用するアニメ
                if (this.TSAList.Count >= 2 && this.PaletteList.Count == 1)
                { //共通パレット
                    List <byte> image_list = new List <byte>();
                    List <byte> tsa_list   = new List <byte>();
                    for (int i = 0; i < anime_list.Count; i++)
                    {
                        p = ra.Write(anime_list[i].image, undodata);
                        U.append_u32(image_list, U.toPointer(p));

                        p = ra.Write(anime_list[i].tsa, undodata);
                        U.append_u32(tsa_list, U.toPointer(p));
                    }

                    ra.WriteAndWritePointer(this.FramePointer, frames.ToArray(), undodata);
                    ra.WriteAndWritePointer(this.TSAPointer, tsa_list.ToArray(), undodata);
                    ra.WriteAndWritePointer(this.ImagePointer, image_list.ToArray(), undodata);
                    ra.WriteAndWritePointer(this.PalettePointer, anime_list[0].pal, undodata);
                }
                else
                {//複数パレット
                    List <byte> image_list = new List <byte>();
                    List <byte> tsa_list   = new List <byte>();
                    List <byte> pal_list   = new List <byte>();
                    for (int i = 0; i < anime_list.Count; i++)
                    {
                        p = ra.Write(anime_list[i].image, undodata);
                        U.append_u32(image_list, U.toPointer(p));

                        p = ra.Write(anime_list[i].tsa, undodata);
                        U.append_u32(tsa_list, U.toPointer(p));

                        p = ra.Write(anime_list[i].pal, undodata);
                        U.append_u32(pal_list, U.toPointer(p));
                    }

                    ra.WriteAndWritePointer(this.FramePointer, frames.ToArray(), undodata);
                    ra.WriteAndWritePointer(this.TSAPointer, tsa_list.ToArray(), undodata);
                    ra.WriteAndWritePointer(this.ImagePointer, image_list.ToArray(), undodata);
                    ra.WriteAndWritePointer(this.PalettePointer, pal_list.ToArray(), undodata);
                }
            }
            ra.BlackOut(undodata);

            Program.Undo.Push(undodata);
            return("");
        }
Exemple #11
0
        public uint MakePaletteUIToROM(uint palette_address, bool isCompress, int palette_index)
        {
            uint addr = U.toOffset(palette_address);

            if (!U.CheckZeroAddressWriteHigh(addr))
            {
                return(U.NOT_FOUND);
            }

            string undo_name = "PALETTE " + U.To0xHexString(palette_address);

            byte[] palttebyte = MakePaletteUIToByte();
            if (isCompress)
            {//戦闘アニメのパレットは圧縮されている
                //現パレットの解凍
                byte[] currentdata = LZ77.decompress(Program.ROM.Data, addr);
                if (currentdata.Length <= 0)
                {//解凍できない アドレスを強引に書き換えたりしたのだろうか.
                    if (palette_index != 0 && palette_index != OVERRAIDE_ALL_PALETTE)
                    {
                        Log.Error("パレットを解凍できません.", U.To0xHexString(addr));
                        return(U.NOT_FOUND);
                    }
                    //解凍できないけど、最初のパレットに書き込むなら、サイズは16*2で固定だから関係ない.
                    currentdata = palttebyte;
                }
                else if (palette_index == OVERRAIDE_ALL_PALETTE)
                {//複数あるパレットですべて同じパレットに設定する
                    int paletteCount = currentdata.Length / 0x20;
                    for (int i = 0; i < paletteCount; i++)
                    {
                        uint write_addr = (uint)(i * 0x20);
                        U.write_range(currentdata, write_addr, palttebyte);
                    }
                }
                else
                {//複数あるパレットの一部を書き換える.
                    uint write_addr = (uint)(palette_index * 0x20);
                    if (currentdata.Length < write_addr + palttebyte.Length)
                    {//サイズが足りない場合増設する.
                        Array.Resize(ref currentdata, (int)(write_addr + palttebyte.Length));
                    }

                    U.write_range(currentdata, write_addr, palttebyte);
                }

                byte[] palettebyteZ = LZ77.compress(currentdata);

                //圧縮されているということは、サイズが可変なわけで、元の場所に書き込めるか、拡張領域かを検討しないといけない。
                Undo.UndoData undodata = Program.Undo.NewUndoData(undo_name);
                uint          newaddr  = InputFormRef.WriteBinaryData(this.SelfForm, addr, palettebyteZ, InputFormRef.get_data_pos_callback_lz77, undodata);
                if (newaddr == U.NOT_FOUND)
                {
                    return(U.NOT_FOUND);
                }
                Program.Undo.Push(undodata);
                return(newaddr);
            }
            else
            {     //無圧縮パレット
                if (palette_index == OVERRAIDE_ALL_PALETTE)
                { //無圧縮パレットでは、パレットのサイズがわからないので、すべて同じ色にすることは不可能
                    R.Error("無圧縮パレットなので、すべて同じパレットにすることはできません。");
                    Debug.Assert(false);
                    return(U.NOT_FOUND);
                }

                addr = addr + (uint)(palette_index * 0x20);

                Program.Undo.Push(undo_name, addr, (uint)palttebyte.Length);
                Program.ROM.write_range(addr, palttebyte);
                return(addr);
            }
        }
        public static string Import(string filename, uint anime_pointer)
        {
            string basename = Path.GetFileNameWithoutExtension(filename) + "_";
            string basedir  = Path.GetDirectoryName(filename);

            //他のアニメーションとはデータ構造が違うので注意
            List <anime> poolList = new List <anime>();
            List <byte>  frames   = new List <byte>();

            string[] lines = File.ReadAllLines(filename);

            for (uint lineCount = 0; lineCount < lines.Length; lineCount++)
            {
                string line = lines[lineCount];
                if (U.IsComment(line) || U.OtherLangLine(line))
                {
                    continue;
                }
                line = U.ClipComment(line);
                if (line.Length <= 0)
                {
                    continue;
                }
                InputFormRef.DoEvents(null, "Line:" + lineCount);

                string[] sp = line.Split(new string[] { "\t" }, StringSplitOptions.RemoveEmptyEntries);
                if (sp.Length <= 1)
                {
                    sp = line.Split(new string[] { " " }, StringSplitOptions.RemoveEmptyEntries);
                }
                if (sp.Length <= 1)
                {
                    continue;
                }

                string command = sp[0];
                uint   wait    = U.atoi0x(command);
                string image   = sp[1];
                uint   song    = 0;
                if (sp.Length >= 2 + 1)
                {
                    song = U.atoi0x(sp[2]);
                }

                string fullfilename = Path.Combine(basedir, image);
                Bitmap bitmap       = ImageUtil.OpenBitmap(fullfilename);
                if (bitmap == null)
                {
                    return(R.Error("ファイル名が見つかりませんでした。\r\nFile: {0} line:{1}\r\n\r\nエラー内容:\r\n{2}", filename, lineCount, line));
                }
                if (bitmap.Width != SCREEN_WIDTH || bitmap.Height != SCREEN_HEIGHT)
                {
                    bitmap = ImageUtil.Copy(bitmap, 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT);
                }

                anime a = new anime();
                a.image = ImageUtil.ImageToByte16Tile(bitmap, SCREEN_WIDTH, SCREEN_HEIGHT);
                a.image = LZ77.compress(a.image);

                a.pal = ImageUtil.ImageToPalette(bitmap, 1);
                poolList.Add(a);

                U.append_u16(frames, wait);
                U.append_u16(frames, song);
                U.append_u32(frames, 0x0);
                U.append_u32(frames, 0x0);
            }
            //term
            U.append_u32(frames, 0x0);
            U.append_u32(frames, 0x0);
            U.append_u32(frames, 0x0);

            byte[] mainData = frames.ToArray();

            anime_pointer = U.toOffset(anime_pointer);
            if (!U.isSafetyOffset(anime_pointer))
            {
                return(R._("アドレスが無効です"));
            }
            uint anime_address = Program.ROM.p32(anime_pointer);

            List <Address> recycle = new List <Address>();

            RecycleOldAnime(ref recycle, basename, false, anime_address);
            RecycleAddress ra = new RecycleAddress(recycle);

            Undo.UndoData undodata = Program.Undo.NewUndoData("ImageUtilMapActionAnimation.Import");

            uint n = 0;

            for (int i = 0; i < poolList.Count; i++, n += 12)
            {
                uint image_addr = CheckDupImage(poolList, i);
                if (image_addr == U.NOT_FOUND)
                {
                    image_addr             = ra.Write(poolList[i].image, undodata);
                    poolList[i].image_addr = image_addr;
                }
                uint pal_addr = CheckDupPal(poolList, i);
                if (pal_addr == U.NOT_FOUND)
                {
                    pal_addr             = ra.Write(poolList[i].pal, undodata);
                    poolList[i].pal_addr = pal_addr;
                }
                U.write_p32(mainData, n + 4, image_addr);
                U.write_p32(mainData, n + 8, pal_addr);
            }

            //アニメポインタの書き換え.
            ra.WriteAndWritePointer(anime_pointer, mainData, undodata);
            //名前の設定
            MakeImportDataName(anime_pointer, filename, lines);

            Program.Undo.Push(undodata);
            return("");
        }
        private void ObjImportButton_Click(object sender, EventArgs e)
        {
            if (this.MapStyle.SelectedIndex < 0)
            {
                return;
            }
            uint obj_plist  = this.MapEditConf[this.MapStyle.SelectedIndex].obj_plist;
            uint obj2_plist = (obj_plist >> 8) & 0xFF; //FE8にはないが FE7は、 plistを2つ設定できることがある.

            Bitmap bitmap = ImageFormRef.ImportFilenameDialog(this);

            if (bitmap == null)
            {
                return;
            }
            int width         = 32 * 8;
            int height        = 32 * 8;
            int palette_count = MAX_MAP_PALETTE_COUNT;

            if (bitmap.Width != width || bitmap.Height < 128)
            {
                R.ShowStopError("画像サイズが正しくありません。\r\nWidth:{2} Height:{3} でなければなりません。\r\n\r\n選択された画像のサイズ Width:{0} Height:{1}", bitmap.Width, bitmap.Height, width, height);
                return;
            }
            height = ImageUtil.CalcHeight(width, width * bitmap.Height / 2);

            if (ObjImportOption.SelectedIndex == 1)
            {//パレットもインポートする場合 パレット数のチェック.
                int bitmap_palette_count = ImageUtil.GetPalette16Count(bitmap);
                if (bitmap_palette_count > palette_count)
                {
                    R.ShowStopError("パレット数が正しくありません。\r\n{1}種類以下(16色*{1}種類) でなければなりません。\r\n\r\n選択された画像のパレット種類:{0}種類", bitmap_palette_count, palette_count);
                    return;
                }
                bitmap = PaletteSwapper(bitmap);
            }

            //画像
            byte[] image = ImageUtil.ImageToByte16Tile(bitmap, width, height);

            //画像等データの書き込み
            Undo.UndoData undodata = Program.Undo.NewUndoData(this);
            if (obj2_plist > 0)
            {//FE7とかあるフィールド画像分割
                byte[] image1  = U.subrange(image, 0, (uint)(image.Length / 2));
                byte[] image2  = U.subrange(image, (uint)(image.Length / 2), (uint)image.Length);
                byte[] image1Z = LZ77.compress(image1);
                byte[] image2Z = LZ77.compress(image2);
                uint   newaddr = InputFormRef.WriteBinaryData(this, (uint)ObjAddress.Value, image1Z, InputFormRef.get_data_pos_callback_lz77, undodata);
                if (newaddr == U.NOT_FOUND)
                {
                    Program.Undo.Rollback(undodata);
                    return;
                }

                ObjAddress.Value = newaddr;
                //拡張領域に書き込んでいる可能性もあるので plstを更新する.
                MapPointerForm.Write_Plsit(MapPointerForm.PLIST_TYPE.OBJECT, obj_plist, newaddr, undodata);

                //分割されたデータを書き込み
                newaddr = InputFormRef.WriteBinaryData(this, (uint)ObjAddress2.Value, image2Z, InputFormRef.get_data_pos_callback_lz77, undodata);
                if (newaddr == U.NOT_FOUND)
                {
                    Program.Undo.Rollback(undodata);
                    return;
                }
                ObjAddress2.Value = newaddr;

                //拡張領域に書き込んでいる可能性もあるので plstを更新する.
                bool r = MapPointerForm.Write_Plsit(MapPointerForm.PLIST_TYPE.OBJECT, obj2_plist, newaddr, undodata);
                if (!r)
                {
                    Program.Undo.Rollback(undodata);
                    return;
                }

                //書き込んだ通知.
                InputFormRef.ShowWriteNotifyAnimation(this, newaddr);
            }
            else
            {
                byte[] imageZ  = LZ77.compress(image);
                uint   newaddr = InputFormRef.WriteBinaryData(this, (uint)ObjAddress.Value, imageZ, InputFormRef.get_data_pos_callback_lz77, undodata);
                if (newaddr == U.NOT_FOUND)
                {
                    Program.Undo.Rollback(undodata);
                    return;
                }
                ObjAddress.Value = newaddr;

                //拡張領域に書き込んでいる可能性もあるので plstを更新する.
                bool r = MapPointerForm.Write_Plsit(MapPointerForm.PLIST_TYPE.OBJECT, obj_plist, newaddr, undodata);
                if (!r)
                {
                    Program.Undo.Rollback(undodata);
                    return;
                }
                //書き込んだ通知.
                InputFormRef.ShowWriteNotifyAnimation(this, newaddr);
            }


            if (ObjImportOption.SelectedIndex == 1)
            {//パレットもインポートする場合
                //パレットの交換
                MapObjImage = bitmap;
                U.ForceUpdate(this.PaletteTypeCombo, 0);
                U.ForceUpdate(this.PaletteCombo, 0);

                //パレット情報の書き込み.
                uint palette_plist   = this.MapEditConf[this.MapStyle.SelectedIndex].palette_plist;
                uint palette_address = MapPointerForm.PlistToOffsetAddr(MapPointerForm.PLIST_TYPE.PALETTE, palette_plist);
                if (palette_address == 0)
                {//未割り当てならば新規確保しようか
                    palette_address = InputFormRef.AppendBinaryData(PaletteFormRef.NewNullPalette(palette_count), undodata);
                }
                PaletteFormRef.MakePaletteBitmapToROM(this, bitmap, palette_address, palette_count, undodata);

                //拡張領域に書き込んでいる可能性もあるので plstを更新する.
                bool r = MapPointerForm.Write_Plsit(MapPointerForm.PLIST_TYPE.PALETTE, palette_plist, palette_address, undodata);
                if (!r)
                {
                    Program.Undo.Rollback(undodata);
                    return;
                }

                PaletteAddress.Value = palette_address;
            }
            else
            {//パレットはインポートしない場合
                //パレット情報の継承.
                bitmap.Palette = this.MapObjImage.Palette;
                //obj Bitmap交換
                this.MapObjImage = bitmap;
            }

            Program.Undo.Push(undodata);

            //チップセットの更新.
            Chipset_Update();
            SelectedChipset_Update();
            MapStyle_SelectedIndexChanged(sender, e);
            InputFormRef.WriteButtonToYellow(this.PaletteWriteButton, false);

            //マップエディタが開いていれば更新する
            MapEditorForm.UpdateMapStyleIfOpen();
        }