コード例 #1
0
        public static void MakeAllDisASMButton(Form self, string store_filename, bool notifyUpdateMessage)
        {
            uint addr = 0x100;

            using (InputFormRef.AutoPleaseWait wait = new InputFormRef.AutoPleaseWait(self))
                using (StreamWriter writer = new StreamWriter(store_filename))
                {
                    writer.WriteLine("//FEBuilderGBA " + R._("逆アセンブラ"));
                    if (notifyUpdateMessage)
                    {
                        writer.WriteLine("//" + DateTime.Now.ToString("yyyyMMdd") + " " + R._("ソースコードを更新する場合は、このファイル消すか、0バイトの空ファイルにしてください。"));
                    }

                    wait.DoEvents("GrepAllStructPointers");

                    AsmMapFile        asmMapFile   = new AsmMapFile(Program.ROM);
                    DisassemblerTrumb Disassembler = new DisassemblerTrumb(asmMapFile);

                    List <DisassemblerTrumb.LDRPointer> ldrmap = Program.AsmMapFileAsmCache.GetLDRMapCache();

                    List <Address> structlist = U.MakeAllStructPointersList(false); //既存の構造体
                    U.AppendAllASMStructPointersList(structlist
                                                     , ldrmap
                                                     , isPatchInstallOnly: false
                                                     , isPatchPointerOnly: false
                                                     , isPatchStructOnly: false
                                                     , isUseOtherGraphics: true
                                                     , isUseOAMSP: true
                                                     );
                    AsmMapFile.InvalidateUNUNSED(structlist);
                    UnpackBINByCode(structlist);
                    MakeFreeData(structlist);
                    asmMapFile.AppendMAP(structlist);

                    //コメントデータ
                    Program.CommentCache.MakeAddressList(structlist);
                    asmMapFile.AppendMAP(structlist);


                    {//設計をミスった。 綺麗なリストを作りたいので、もう一回読みこみなおそう...
                        AsmMapFile asmMapFile2 = new AsmMapFile(Program.ROM);
                        asmMapFile2.MakeAllDataLength(structlist);
                        AsmMapFile.InvalidateUNUNSED(structlist);
                    }

                    uint limit = (uint)Program.ROM.Data.Length;

                    int                     jisage          = 0;                             //字下げする数
                    string                  jisageSpaceData = "";                            //字下げに利用するマージンデータ
                    List <uint>             jmplabel        = new List <uint>();             //ジャンプラベル 字下げに使う
                    Dictionary <uint, uint> ldrtable        = new Dictionary <uint, uint>(); //LDR参照データがある位置を記録します. コードの末尾などにあります. 数が多くなるのでマップする.
                    AsmMapFile.MakeSwitchDataList(ldrtable, 0x100, 0);

                    wait.DoEvents(R._("データを準備中..."));
                    //探索を早くするために、データをアドレスへマッピングする. メモリを大量に使うが早い.
                    Dictionary <uint, Address> lookupStructMap = MakeAllStructMapping(structlist);
                    structlist = null;

                    uint    nextDoEvents = 0;
                    bool    prevPointer  = false; //ひとつ前がポインタだった
                    Address matchAddress;
                    DisassemblerTrumb.VM vm = new DisassemblerTrumb.VM();
                    while (addr < limit)
                    {
                        if (addr > nextDoEvents)
                        {//毎回更新するのは無駄なのである程度の間隔で更新して以降
                            wait.DoEvents(String.Format("{0}/{1}", addr, limit));
                            nextDoEvents = addr + 0xfff;
                        }


                        if (lookupStructMap.TryGetValue(addr, out matchAddress))
                        {
                            if (matchAddress.Pointer <= addr && addr < matchAddress.Pointer + 4)
                            {//ポインタ?
                                writer.WriteLine(U.toPointer(addr).ToString("X08") + " " + U.MakeOPData(addr, 4) + "   //POINTER " + matchAddress.Info);
                                addr += 4;
                            }
                            else
                            {//データ
                                uint newaddr = U.Padding2(matchAddress.Addr + matchAddress.Length);
                                uint length  = (newaddr - addr);
                                Debug.Assert(length < 10000000);
                                writer.WriteLine("{0} - {1} //{2} ({3}bytes)", U.toPointer(addr).ToString("X08"), U.toPointer(newaddr).ToString("X08"), matchAddress.Info, length);
                                addr = U.Padding4(newaddr);
                            }
                            prevPointer = true;
                            continue;
                        }

                        //LDR参照とスイッチ参照
                        if (ldrtable.ContainsKey(addr))
                        {//LDR参照のポインタデータが入っている
                            uint ldr = ldrtable[addr];
                            if (ldr == U.NOT_FOUND)
                            {//switch case
                                writer.WriteLine(U.toPointer(addr).ToString("X08") + " " + U.MakeOPData(addr, 4) + "   //SWITCH CASE");
                            }
                            else
                            {
                                writer.WriteLine(U.toPointer(addr).ToString("X08") + " " + U.MakeOPData(addr, 4) + "   //LDRDATA");
                            }
                            addr       += 4;
                            prevPointer = true;
                            continue;
                        }

                        if (prevPointer)
                        {//ひとつ前がポインタの場合、野生のポインタをチェック
                            uint data = Program.ROM.u32(addr);
                            if (U.isPointer(data))
                            {
                                if (lookupStructMap.TryGetValue(U.toOffset(data), out matchAddress))
                                {
                                    writer.WriteLine(U.toPointer(addr).ToString("X08") + " " + U.MakeOPData(addr, 4) + "   //Wild POINTER " + U.ToHexString8(data) + " " + matchAddress.Info);
                                    addr += 4;
                                    continue;
                                }
                            }
                        }

                        //ひとつ前はポインタではない.
                        prevPointer = false;

                        //Disassembler
                        DisassemblerTrumb.Code code =
                            Disassembler.Disassembler(Program.ROM.Data, addr, limit, vm);
                        if (code.Type == DisassemblerTrumb.CodeType.BXJMP)
                        {//関数の出口なので字下げをすべて取り消す.
                            jisage = 0;
                            jmplabel.Clear();
                            jisageSpaceData = "";
                        }
                        else
                        {
                            for (int i = 0; i < jmplabel.Count;)
                            {
                                if (addr >= jmplabel[i])
                                {
                                    jmplabel.RemoveAt(i);
                                    jisage--;
                                    jisageSpaceData = U.MakeJisageSpace(jisage);
                                    i = 0;
                                    continue;
                                }
                                i++;
                            }
                        }

                        writer.WriteLine(jisageSpaceData + U.toPointer(addr).ToString("X08") + " " + U.MakeOPData(addr, code.GetLength()) + "   " + code.ASM.ToLower() + code.Comment);

                        if (code.Type == DisassemblerTrumb.CodeType.CONDJMP //条件式なので字下げ開始
                            )
                        {
                            uint jumplabel = U.toOffset(code.Data);
                            if (addr < jumplabel)
                            {//とび先が自分より後ろであること. 前方はすでに過ぎてしまったので字下げできない.
                                jisage++;
                                jmplabel.Add(jumplabel);
                                jisageSpaceData = U.MakeJisageSpace(jisage);
                            }
                        }
                        else if (code.Type == DisassemblerTrumb.CodeType.BXJMP)
                        {//関数の終わりなので空行を入れる.
                            writer.WriteLine("");
                        }

                        if (code.Type == DisassemblerTrumb.CodeType.LDR)
                        {//LDR参照位置を記録していく.
                            ldrtable[code.Data2] = addr;
                        }

                        addr += code.GetLength();
                    }
                }

            if (self != null)
            {
                //エクスプローラで選択しよう
                U.SelectFileByExplorer(store_filename);
            }
        }