static bool IsWarpChapterFE8(uint chapterID)
        {
            PatchUtil.mnc2_fix_enum use_mnc2 = PatchUtil.SearchSkipWorldMapPatch();
            if (use_mnc2 == PatchUtil.mnc2_fix_enum.NO)
            {
                if (MapLoadFunctionForm.IsEnterChapterAlways(chapterID))
                {
                    return(true);
                }
            }

            return(true);
        }
        public static bool CheckAndShowPopupDialog(TYPE type)
        {
            Func <bool> checkFunc     = null;
            string      reason        = "";
            string      patchName1    = "";
            string      patchName2    = "";
            string      patchShowName = null;
            string      patchCombo    = "";

            if (type == TYPE.Anti_Huffman_By_Translate)
            {
                checkFunc  = PatchUtil.SearchAntiHuffmanPatch;
                reason     = R._("翻訳された文章がハフマン符号化テーブルを超えている可能性があります。\r\nAntiHuffmanPatchを適応しておくことをお勧めします。");
                patchName1 = "Anti-Huffman";///No Translate
            }
            if (type == TYPE.Anti_Huffman_By_English)
            {
                checkFunc  = PatchUtil.SearchAntiHuffmanPatch;
                reason     = R._("英語版で、テキストを変更するためには、Anti-Huffman Patchが必要です。");
                patchName1 = "Anti-Huffman";///No Translate
            }
            else if (type == TYPE.C01Hack_By_ImageBattleAnimation)
            {
                checkFunc  = PatchUtil.SearchC01HackPatch;
                reason     = R._("このアニメーションには、C01 命令が使われています。\r\n現在、C01ハックパッチは、まだインストールされていません。\r\nアニメーションを再生するためには、\r\nC01ハックを有効にした方がいいと思われますが、どうしますか?\r\n");
                patchName1 = "01command_hack"; ///No Translate
                patchName2 = "01コマンドハック";      ///No Translate
            }
            else if (type == TYPE.C48Hack_By_ImageBattleAnimation)
            {
                checkFunc  = PatchUtil.SearchC48HackPatch;
                reason     = R._("このアニメーションには、C48 命令(or Sxx命令)が使われています。\r\n現在、C48ハックパッチは、まだインストールされていません。\r\nアニメーションを再生するためには、\r\nC48ハックを有効にした方がいいと思われますが、どうしますか?\r\n");
                patchName1 = "48command_hack"; ///No Translate
                patchName2 = "48コマンドハック";      ///No Translate
            }
            else if (type == TYPE.NIMAP_By_SongTrack)
            {
                checkFunc = PatchUtil.SearchNIMAP;
                reason    = R._("Midi楽器はFE楽器と並び順が違うので、\r\nNIMAPを利用することをお勧めします。");
                if (Program.ROM.RomInfo.version() == 8)
                {                                                       //FE8用には更新されたバージョンを利用する.
                    patchName1 = "SOUND_NIMAP2(Native Instrument Map)"; ///No Translate
                    patchName2 = "SOUND_NIMAP2";                        ///No Translate
                }
                else
                {
                    patchName1 = "SOUND_NIMAP(Native Instrument Map)"; ///No Translate
                    patchName2 = "SOUND_NIMAP";                        ///No Translate
                }
            }
            else if (type == TYPE.Track12_Over_By_SongTrack)
            {
                checkFunc  = PatchUtil.Search16tracks12soundsPatch;
                reason     = R._("この楽曲の楽譜は、12以上のトラックが存在しています。\r\nこの曲をゲームで再生するには、16_tracks_12_soundsが必要です。\r\nこのパッチを適応しますか?");
                patchName1 = "16_tracks_12_sounds";///No Translate
            }
            else if (type == TYPE.MeleeAndMagicFix_By_Unit)
            {
                checkFunc  = PatchUtil.SearchMeleeAndMagicFixPatch;
                reason     = R._("武器と魔法を同時に利用するにはMeleeAndMagicPatchが必要です。\r\n有効にしますか?");
                patchName1 = "MeleeAndMagicFix";///No Translate
            }
            else if (type == TYPE.ItemIconExpands)
            {
                checkFunc  = PatchUtil.SearchIconExpandsPatch;
                reason     = R._("アイコンを拡張するには、テーブルを拡張する前にパッチを適応する必要があります。\r\n有効にしますか?");
                patchName1 = "Extended to item icon 0xFE";   ///No Translate
                patchName2 = "Extend Item Icon List Length"; ///No Translate
                patchCombo = "fix";
            }
            else if (type == TYPE.MagicPatch_By_Menu)
            {
                return(HowDoYouLikePatch2Form.CheckAndShowPopupDialog(HowDoYouLikePatch2Form.TYPE.MagicPatch_By_Menu));
            }
            else if (type == TYPE.Skill)
            {
                if (Program.ROM.RomInfo.version() != 8)
                {
                    return(false);
                }
                if (Program.ROM.RomInfo.is_multibyte())
                {
                    checkFunc = () =>
                    {
                        PatchUtil.skill_system_enum a = PatchUtil.SearchSkillSystem();
                        return(a == PatchUtil.skill_system_enum.FE8N ||
                               a == PatchUtil.skill_system_enum.FE8N_ver2 ||
                               a == PatchUtil.skill_system_enum.yugudora
                               );
                    };
                    reason     = R._("スキル拡張 FE8N が必要です。\r\n有効にしますか?");
                    patchName1 = "Skill Extension FE8N 2019_02_19"; ///No Translate
                    patchName2 = "skill_2019_02_19";                ///No Translate
                }
                else
                {
                    checkFunc = () =>
                    {
                        return(PatchUtil.SearchSkillSystem() == PatchUtil.skill_system_enum.SkillSystem);
                    };
                    reason     = R._("スキル拡張 SkillSystems が必要です。\r\n有効にしますか?");
                    patchName1 = "Skill20200223"; ///No Translate
                    patchName2 = "Skill20200223"; ///No Translate
                }
            }
            else if (type == TYPE.SkipWorldmapFix)
            {
                if (Program.ROM.RomInfo.version() != 8)
                {
                    return(false);
                }

                checkFunc = () =>
                {
                    return(PatchUtil.SearchSkipWorldMapPatch() != PatchUtil.mnc2_fix_enum.NO);
                };
                reason        = R._("FE8のマップをワールドマップを経由しないで移動させるには、パッチが必要です。\r\n有効にしますか?");
                patchName1    = "MNC2Fix"; ///No Translate
                patchName2    = "MNC2Fix"; ///No Translate
                patchShowName = "Skip Worldmap";
                patchCombo    = "fix";
            }
            else if (type == TYPE.CAMERA_Event_OutOfBand_Fix)
            {
                if (Program.ROM.RomInfo.version() != 8)
                {
                    return(false);
                }

                checkFunc = () =>
                {
                    return(PatchUtil.SearchCAMERA_Event_OutOfBand_FixPatch());
                };
                reason        = R._("カメラを移動する命令で、画面外に飛び出してしまうバグを修正するパッチをインストールしますか?");
                patchName1    = "Fix CAM1_CAMERA2 going out of bounds"; ///No Translate
                patchName2    = "Fix CAM1_CAMERA2 going out of bounds"; ///No Translate
                patchShowName = "Fix CAM1_CAMERA2 going out of bounds";
                patchCombo    = "Fix";
            }
            else if (type == TYPE.CAMERA_Event_NotExistsUnit_Fix)
            {
                if (Program.ROM.RomInfo.version() != 8)
                {
                    return(false);
                }

                checkFunc = () =>
                {
                    return(PatchUtil.SearchCAMERA_Event_NotExistsUnit_FixPatch());
                };
                reason        = R._("存在しないユニットを指定した時にフリーズするバグを修正するパッチをインストールしますか?");
                patchName1    = "Event26_CameraControlMaybe_Fix not to freeze even nonexistent units"; ///No Translate
                patchName2    = "Event26_CameraControlMaybe_Fix not to freeze even nonexistent units"; ///No Translate
                patchShowName = "Event26_CameraControlMaybe_Fix not to freeze even nonexistent units";
                patchCombo    = "Fix";
            }
            else if (type == TYPE.UnitStateEvent_0x34_Fix)
            {
                if (Program.ROM.RomInfo.version() != 8)
                {
                    return(false);
                }

                checkFunc = () =>
                {
                    return(PatchUtil.SearchUnitStateEvent_0x34_FixPatch());
                };
                reason        = R._("存在しないユニットを指定した時にフリーズするバグを修正するパッチをインストールしますか?");
                patchName1    = "Event34_MessWithUnitState_Fix not to freeze even nonexistent units"; ///No Translate
                patchName2    = "Event34_MessWithUnitState_Fix not to freeze even nonexistent units"; ///No Translate
                patchShowName = "Event34_MessWithUnitState_Fix not to freeze even nonexistent units";
                patchCombo    = "Fix";
            }
            else if (type == TYPE.WakuEvent_0x3B_Fix)
            {
                if (Program.ROM.RomInfo.version() != 8)
                {
                    return(false);
                }

                checkFunc = () =>
                {
                    return(PatchUtil.SearchWakuEvent_0x3B_FixPatch());
                };
                reason        = R._("存在しないユニットを指定した時にフリーズするバグを修正するパッチをインストールしますか?");
                patchName1    = "Event3B_frame_Fix not to freeze even nonexistent units"; ///No Translate
                patchName2    = "Event3B_frame_Fix not to freeze even nonexistent units"; ///No Translate
                patchShowName = "Event3B_frame_Fix not to freeze even nonexistent units";
                patchCombo    = "Fix";
            }

            Debug.Assert(checkFunc != null);
            Debug.Assert(patchName1 != "");
            Debug.Assert(reason != "");
            if (checkFunc())
            {//すでに適応されている.
                return(true);
            }
            if (patchShowName == null)
            {
                patchShowName = patchName1;
            }

            HowDoYouLikePatchForm f = (HowDoYouLikePatchForm)InputFormRef.JumpFormLow <HowDoYouLikePatchForm>();
            string tile             = R._("{0}パッチを有効にしますか?", patchShowName);

            f.Text                = tile;
            f.ReasonLabel.Text    = R._("{0}\r\n\r\n{1}", tile, reason);
            f.EnableButton.Text   = R._("{0}パッチを有効にする", patchShowName);
            f.EnableButton.Click += (sender, e) => {
                f.Close();
                PatchForm patchF = (PatchForm)InputFormRef.JumpForm <PatchForm>();
                bool      r      = patchF.ApplyPatch(patchName1, patchName2, patchCombo); ///No Translate
                if (!r)
                {
                    R.ShowStopError("パッチの自動適応に失敗しました。\r\nパッチ画面にエラーが表示されていないか確認してください。\r\n必須パッチの適応に失敗したということは、FEBuilderGBAの解凍に失敗している可能性があります。\r\nFEBuilderGBAを再インストールしてください。\r\nそれでも問題が解決しない場合は、バグとして報告してください。\r\n");
                }
                f.Close();
            };

            if (Program.IsCommandLine)
            {//コマンドラインモードだったら自動適応するしかないね。
                U.FireOnClick(f.EnableButton);
                return(checkFunc());
            }

            f.ShowDialog();

            return(checkFunc());
        }
        public static void CHEAT_WARP_FE8(EmulatorMemoryForm form, uint warp_chapter, uint edtion, uint worldmap_node)
        {
            Debug.Assert(Program.ROM.RomInfo.version() == 8);

            uint work_address = Program.ROM.RomInfo.workmemory_last_string_address() - 0x70; //テキストバッファの一番下をデータ置き場として利用する.
            uint gSomeWMEventRelatedStruct;
            uint eventExecuteFucntion;
            uint endAllMenusFunction;
            uint deletePlayerPhaseInterface6CsFunction;

            if (Program.ROM.RomInfo.is_multibyte())
            {//FE8J
                gSomeWMEventRelatedStruct             = 0x03005270;
                eventExecuteFucntion                  = 0x0800D340;
                endAllMenusFunction                   = 0x0804FCAC;
                deletePlayerPhaseInterface6CsFunction = 0x0808F44C;
            }
            else
            {//FE8U
                gSomeWMEventRelatedStruct             = 0x03005280;
                eventExecuteFucntion                  = 0x0800D07C;
                endAllMenusFunction                   = 0x0804ef20;
                deletePlayerPhaseInterface6CsFunction = 0x0808d150;
            }

            //Search MAPTASK Procs
            uint maptask = SearchMapTaskProcsAddr();

            if (maptask == U.NOT_FOUND)
            {
                R.ShowStopError("MAPTASK Procsの位置を特定できませんでした。\r\n章に入っていますか?\r\nこの機能を使うには章の中に入らないといけません。");
                return;
            }

            byte[] warpCode =
            {
                //ASM
                0x00, 0xB5, 0x12, 0x4A, 0x42, 0x60, 0x12, 0x4B, 0x9E, 0x46, 0x00, 0xF8, 0x11, 0x4B, 0x9E, 0x46, 0x00, 0xF8, 0x78, 0x46, 0x0E, 0x30, 0x01, 0x21, 0x0F, 0x4B, 0x9E, 0x46, 0x00, 0xF8, 0x01, 0xBC, 0x00, 0x47, 0xC0, 0x46,
                //Event +24
                0x22, 0x2A, 0xFF, 0xFF,                         //MNC2
                0x28, 0x02, 0x07, 0x00, 0x20, 0x01, 0x00, 0x00, //NoFade+Term
                0x00, 0x00, 0x00, 0x00,                         //padding
                //hook procs +34
                0x02, 0x00, 0x00, 0x00, 0x61, 0xB6, 0x02, 0x02, 0x0E, 0x00, 0x78, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                0x30, 0x5E, 0x5C, 0x08, //backCode
                0xAC, 0xFC, 0x04, 0x08,
                0x4C, 0xF4, 0x08, 0x08,
                0x40, 0xD3, 0x00, 0x08 //eventExecuteFucntion
            };

            PatchUtil.mnc2_fix_enum use_mnc2 = PatchUtil.SearchSkipWorldMapPatch();
            if (use_mnc2 != PatchUtil.mnc2_fix_enum.NO ||
                MapLoadFunctionForm.IsEnterChapterAlways(warp_chapter))
            {//MNC2でワープ可能
                //章ID
                U.write_u16(warpCode, 0x26, warp_chapter);
            }
            else
            {//MNCHが必要
                uint worldmap_node_minus1 = 0;
                if (worldmap_node > 0)
                {
                    worldmap_node_minus1 = worldmap_node - 1;
                }

                byte[] mnch_code =
                {
                    0x40, 0xA6,                       0x00, 0x00,
                    0x00, 0x00, (byte)worldmap_node_minus1, 0x00,
                    0x21, 0x2A, (byte)warp_chapter,         0x00,
                    0x20, 0x01,                       0x00, 0x00,
                };
                U.write_range(warpCode, 0x24, mnch_code);
            }

            //Procsで実行を指定するASMコードの位置
            U.write_u32(warpCode, 0x38, work_address + 1);

            //メニューがあれば閉じる命令
            U.write_u32(warpCode, 0x50, endAllMenusFunction);
            //TI PIなどのプレイヤーUIがあれば閉じる命令
            U.write_u32(warpCode, 0x54, deletePlayerPhaseInterface6CsFunction);

            //イベント命令を実行する命令
            U.write_u32(warpCode, 0x58, eventExecuteFucntion);

            //復帰するProcsのコード
            uint backCode = Program.RAM.u32(maptask + 4);

            U.write_u32(warpCode, 0x4C, backCode);
            Program.RAM.write_range(work_address, warpCode);

            uint procs_jump_addr = work_address + 0x34;

            Program.RAM.write_u32(maptask + 4, procs_jump_addr);

            //Edition
            uint stageStructAddr = Program.ROM.RomInfo.workmemory_mapid_address() - 0xE;

            Program.RAM.write_u8(stageStructAddr + 0x1b, edtion);

            //拠点
            Program.RAM.write_u8(gSomeWMEventRelatedStruct + 0x11, worldmap_node);

            InputFormRef.ShowWriteNotifyAnimation(form, procs_jump_addr);
            return;
        }
        public static bool CheckAndShowPopupDialog(TYPE type)
        {
            Func <bool> checkFunc = null;
            string      title     = "";
            string      reason    = "";

            string patchName1    = "";
            string patchName2    = "";
            string patchShowName = null;
            string patchCombo1   = "";

            string patchName3     = "";
            string patchName4     = "";
            string patchShowName3 = null;
            string patchCombo3    = "";

            if (type == TYPE.MagicPatch_By_Menu)
            {
                checkFunc = () => {
                    return(ImageUtilMagic.SearchMagicSystem() != ImageUtilMagic.magic_system_enum.NO);
                };
                title = R._("魔法を追加するには、魔法システムパッチが必要です。");
                string version = Program.ROM.RomInfo.VersionToFilename();
                if (version == "FE6")
                {                                            //FE6
                    //patchName1 = "FEditorMagicCSASystem_FE6";///No Translate
                    patchName3 = "CSA_Creator_For_FE6_ver2"; ///No Translate
                }
                else if (version == "FE7J")
                {                                                 //FE7J
                    patchName1 = "Custom Spell Animation Engine"; ///No Translate
                    //patchName3 = "CSA_Creator_For_FE7U";///No Translate

//                    string no_patch = R._("残念ながら、FE7J用の魔法システムパッチは存在しません。\r\n");
//                    R.ShowStopError(title + "\r\n" + no_patch);
//                    return false;
                }
                else if (version == "FE7U")
                {                                             //FE7U
                    //patchName1 = "FEditorMagicCSASystem_FE7U";///No Translate
                    patchName3 = "CSA_Creator_For_FE7U_ver2"; ///No Translate
                }
                else if (version == "FE8J")
                {                                                       //FE8J
                    patchName1 = "magic patch (FeditorAdvMagicSystem)"; ///No Translate
                    patchName3 = "CSA_Creator_For_FE8J_ver2";           ///No Translate
                }
                else if (version == "FE8U")
                {                                              //FE8U
                    patchName1 = "FEditorMagicCSASystem_FE8U"; ///No Translate
                    patchName3 = "CSA_Creator_For_FE8U_ver2";  ///No Translate
                }

                if (patchName1 != "" && patchName3 != "")
                {
                    reason  = R._("魔法システムパッチは2つあるので、どちらかを選んでください。\r\n");
                    reason += R._("FEditorMagicCSASystemは、長い動作実績のある魔法システムです。\r\n");
                    reason += R._("CSA_Creatorは、より解像度をサポートする、新進気鋭の魔法システムです。\r\n");
                }
                else
                {
                    reason = R._("魔法システムパッチを適用してください。");
                }
            }
            else if (type == TYPE.DrawFont_By_Translate)
            {
                checkFunc = () => { return(PatchUtil.draw_font_enum.NO != PatchUtil.SearchDrawFontPatch()); };
                title     = R._("他の言語を表示するにはDrawFontパッチが必要です。");
                if (Program.ROM.RomInfo.is_multibyte())
                {
                    patchName3 = "DrawSingleByte";///No Translate
                }
                else
                {
                    patchName1 = "DrawMultiByte"; ///No Translate
                    patchName3 = "DrawUTF8";      ///No Translate

                    reason += R._("日本語へ翻訳する場合は、DrawMultiByte を選択してください。\r\n");
                    reason += R._("日本語以外へ翻訳する場合は、DrawUTF8 を選択してください\r\n");
                }
            }
            else if (type == TYPE.SkipWorldmapFix)
            {
                if (Program.ROM.RomInfo.version() != 8)
                {
                    return(false);
                }

                checkFunc = () =>
                {
                    return(PatchUtil.SearchSkipWorldMapPatch() != PatchUtil.mnc2_fix_enum.NO);
                };
                title   = R._("FE8のマップをワールドマップを経由しないで移動させるには、パッチが必要です。\r\n有効にしますか?");
                reason  = R._("フリーマップを無効にしてよいならば、強力なEliminateを選択してください。\r\n");
                reason += R._("フリーマップを使いたい場合は、MNC2Fix を選択してください。\r\n");

                patchName1  = "Eliminate";                                                                 ///No Translate
                patchName2  = "Eliminate the constraint of freezing unless it enters from the world map."; ///No Translate
                patchCombo1 = "fix";                                                                       ///No Translate

                patchName3 = "MNC2Fix";                                                                    ///No Translate
                patchName4 = "MNC2Fix";                                                                    ///No Translate
            }

            Debug.Assert(checkFunc != null);
            Debug.Assert(title != "");
            if (checkFunc())
            {//すでに適応されている.
                return(true);
            }
            if (IgnorePatchs.IndexOf(type) >= 0)
            {
                return(true);
            }
            if (patchShowName == null)
            {
                patchShowName = patchName1;
            }
            if (patchShowName3 == null)
            {
                patchShowName3 = patchName3;
            }

            HowDoYouLikePatch2Form f = (HowDoYouLikePatch2Form)InputFormRef.JumpFormLow <HowDoYouLikePatch2Form>();

            f.CurrentType      = type;
            f.Text             = title;
            f.ReasonLabel.Text = R._("{0}\r\n\r\n{1}", title, reason);

            if (patchName1 == "")
            {
                f.EnableButton.Hide();
            }
            else
            {
                f.EnableButton.Text   = R._("{0}パッチを有効にする", patchShowName);
                f.EnableButton.Click += (sender, e) =>
                {
                    f.Close();

                    PatchForm patchF = (PatchForm)InputFormRef.JumpForm <PatchForm>();
                    patchF.ApplyPatch(patchName1, patchName2, patchCombo1); ///No Translate
                };
            }

            if (patchName3 == "")
            {
                f.EnableButton3.Hide();
            }
            else
            {
                f.EnableButton3.Text   = R._("{0}パッチを有効にする", patchShowName3);
                f.EnableButton3.Click += (sender, e) =>
                {
                    f.Close();

                    PatchForm patchF = (PatchForm)InputFormRef.JumpForm <PatchForm>();
                    patchF.ApplyPatch(patchName3, patchName4, patchCombo3); ///No Translate
                };
            }

            if (Program.IsCommandLine)
            {//コマンドラインモードだったら自動適応するしかないね。
                f.CommandLineClick(patchName1, patchName3);
                return(checkFunc());
            }

            f.ShowDialog();

            return(checkFunc());
        }