DebugConsole.java
     1: //========================================================================================
     2: //  DebugConsole.java
     3: //    en:Debug console -- An interactive debugger
     4: //    ja:デバッグコンソール -- 対話型デバッガ
     5: //  Copyright (C) 2003-2024 Makoto Kamada
     6: //
     7: //  This file is part of the XEiJ (X68000 Emulator in Java).
     8: //  You can use, modify and redistribute the XEiJ if the conditions are met.
     9: //  Read the XEiJ License for more details.
    10: //  https://stdkmd.net/xeij/
    11: //========================================================================================
    12: 
    13: package xeij;
    14: 
    15: import java.awt.*;  //BasicStroke,BorderLayout,BoxLayout,Color,Component,Container,Cursor,Desktop,Dimension,Font,FlowLayout,Frame,Graphics,Graphics2D,GraphicsDevice,GraphicsEnvironment,GridLayout,Image,Insets,Paint,Point,Rectangle,RenderingHints,Robot,Shape,Stroke,TexturePaint,Toolkit
    16: import java.awt.datatransfer.*;  //Clipboard,DataFlavor,FlavorEvent,FlavorListener,Transferable,UnsupportedFlavorException
    17: import java.awt.event.*;  //ActionEvent,ActionListener,ComponentAdapter,ComponentEvent,ComponentListener,FocusAdapter,FocusEvent,FocusListener,InputEvent,KeyAdapter,KeyEvent,KeyListener,MouseAdapter,MouseEvent,MouseListener,MouseMotionAdapter,MouseWheelEvent,WindowAdapter,WindowEvent,WindowListener,WindowStateListener
    18: import java.lang.*;  //Boolean,Character,Class,Comparable,Double,Exception,Float,IllegalArgumentException,Integer,Long,Math,Number,Object,Runnable,SecurityException,String,StringBuilder,System
    19: import java.util.*;  //ArrayList,Arrays,Calendar,GregorianCalendar,HashMap,Map,Map.Entry,LinkedList,TimeZone,Timer,TimerTask,TreeMap
    20: import javax.swing.*;  //AbstractButton,AbstractSpinnerModel,Box,ButtonGroup,DefaultListModel,ImageIcon,JApplet,JButton,JCheckBox,JCheckBoxMenuItem,JComponent,JDialog,JFileChooser,JFrame,JLabel,JList,JMenu,JMenuBar,JMenuItem,JPanel,JRadioButton,JScrollPane,JSpinner,JTextArea,JTextField,JTextPane,JViewport,ScrollPaneConstants,SpinnerListModel,SpinnerNumberModel,SwingConstants,SwingUtilities,UIManager,UIDefaults,UnsupportedLookAndFeelException
    21: import javax.swing.event.*;  //CaretEvent,CaretListener,ChangeEvent,ChangeListener,DocumentEvent,DocumentListener,ListSelectionListener
    22: 
    23: public class DebugConsole {
    24: 
    25:   public static final int DGT_MAX_OUTPUT_LENGTH = 1024 * 1024;  //出力の上限を1MBとする
    26:   public static final int DGT_CUT_OUTPUT_LENGTH = DGT_MAX_OUTPUT_LENGTH + 1024 * 64;  //出力が上限よりも64KB以上長くなったら上限でカットする
    27: 
    28:   //入力モード
    29:   public static final int DGT_INPUT_MODE_COMMAND   = 1;  //コマンドモード
    30:   public static final int DGT_INPUT_MODE_PAGE      = 2;  //ページモード
    31:   public static final int DGT_INPUT_MODE_ASSEMBLER = 3;  //アセンブラモード
    32:   public static int dgtInputMode;  //入力モード
    33:   public static LinkedList<String> dgtPageList;
    34: 
    35:   //プロンプト
    36:   public static final String DGT_COMMAND_PROMPT = "> ";
    37:   public static final String DGT_PAGE_PROMPT = "-- more -- [y/n] ";
    38:   public static String dgtCurrentPrompt;  //現在のプロンプト
    39: 
    40:   //コンポーネント
    41:   public static JFrame dgtFrame;  //ウインドウ
    42:   public static ScrollTextArea dgtBoard;  //テキストエリア
    43:   public static JPopupMenu dgtPopupMenu;  //ポップアップメニュー
    44:   public static JMenuItem dgtPopupCutMenuItem;  //切り取り
    45:   public static JMenuItem dgtPopupCopyMenuItem;  //コピー
    46:   public static JMenuItem dgtPopupPasteMenuItem;  //貼り付け
    47:   public static JMenuItem dgtPopupSelectAllMenuItem;  //すべて選択
    48:   public static int dgtOutputEnd;  //出力された文字列の末尾。リターンキーが押されたらこれ以降に書かれた文字列をまとめて入力する
    49: 
    50:   //コアが停止したときコンソールに何を表示するか
    51:   //  bit0  整数レジスタを表示する
    52:   //  bit1  浮動小数点レジスタを表示する
    53:   //  bit2  プロンプトを表示する。レジスタの表示を繰り返すときは最終回だけセットする
    54:   public static volatile int dgtRequestRegs;
    55: 
    56:   //アセンブル
    57:   public static int dgtAssemblePC;  //次にアセンブルするアドレス
    58:   public static int dgtAssembleFC;  //次にアセンブルするファンクションコード
    59: 
    60:   //逆アセンブル
    61:   public static int dgtDisassembleLastTail;  //前回逆アセンブルした範囲の終了アドレス
    62:   public static int dgtDisassemblePC;  //前回逆アセンブルした範囲の直後のアドレス。0=PCを使う
    63:   public static int dgtDisassembleFC;  //前回逆アセンブルした範囲のファンクションコード
    64: 
    65:   //ダンプ
    66:   public static int dgtDumpAddress;  //次回のダンプ開始アドレス
    67:   public static int dgtDumpFunctionCode;  //ファンクションコード
    68:   public static int dgtDumpStraddleChar;  //2行に跨る文字
    69: 
    70:   //dgtInit ()
    71:   //  デバッグコンソールを初期化する
    72:   public static void dgtInit () {
    73:     dgtInputMode = DGT_INPUT_MODE_COMMAND;
    74:     dgtPageList = null;
    75:     dgtCurrentPrompt = DGT_COMMAND_PROMPT;
    76:     dgtFrame = null;
    77:     dgtBoard = null;
    78:     dgtPopupMenu = null;
    79:     dgtPopupCutMenuItem = null;
    80:     dgtPopupCopyMenuItem = null;
    81:     dgtPopupPasteMenuItem = null;
    82:     dgtPopupSelectAllMenuItem = null;
    83:     dgtOutputEnd = dgtCurrentPrompt.length ();
    84:     dgtRequestRegs = 0;
    85:     dgtAssemblePC = 0;
    86:     dgtAssembleFC = 6;
    87:     dgtDisassembleLastTail = 0;
    88:     dgtDisassemblePC = 0;
    89:     dgtDisassembleFC = 6;
    90:     dgtDumpAddress = 0;
    91:     dgtDumpFunctionCode = 5;
    92:     dgtDumpStraddleChar = 0;
    93:   }  //dgtInit()
    94: 
    95:   //dgtMake ()
    96:   //  デバッグコンソールを作る
    97:   //  ここでは開かない
    98:   public static void dgtMake () {
    99: 
   100:     //テキストエリア
   101:     String initialText = (Multilingual.mlnJapanese ?
   102:                           "[ h で使用法を表示]\n" :
   103:                           "[enter h to display usage]\n") + dgtCurrentPrompt;
   104:     dgtOutputEnd = initialText.length ();
   105:     dgtBoard = ComponentFactory.createScrollTextArea (initialText, 500, 600, true);
   106:     dgtBoard.setUnderlineCursorOn (true);
   107:     dgtBoard.setLineWrap (true);  //行を折り返す
   108:     dgtBoard.addDocumentListener (new DocumentListener () {
   109:       @Override public void changedUpdate (DocumentEvent de) {
   110:       }
   111:       @Override public void insertUpdate (DocumentEvent de) {
   112:         if (de.getOffset () < dgtOutputEnd) {
   113:           dgtOutputEnd += de.getLength ();  //出力された文字列の末尾を調整する
   114:         }
   115:       }
   116:       @Override public void removeUpdate (DocumentEvent de) {
   117:         if (de.getOffset () < dgtOutputEnd) {
   118:           dgtOutputEnd -= Math.min (de.getLength (), dgtOutputEnd - de.getOffset ());  //出力された文字列の末尾を調整する
   119:         }
   120:       }
   121:     });
   122:     dgtBoard.addKeyListener (new KeyAdapter () {
   123:       @Override public void keyPressed (KeyEvent ke) {
   124:         int code = ke.getKeyCode ();
   125:         int modifiersEx = ke.getModifiersEx ();
   126:         if (code == KeyEvent.VK_ENTER &&  //Enterキーが押された
   127:             (modifiersEx & (InputEvent.ALT_DOWN_MASK |
   128:                             InputEvent.CTRL_DOWN_MASK |
   129:                             InputEvent.META_DOWN_MASK)) == 0) {  //Altキー,Ctrlキー,Metaキーが押されていない
   130:           if ((modifiersEx & InputEvent.SHIFT_DOWN_MASK) == 0) {  //Shiftキーが押されていない
   131:             ke.consume ();  //Enterキーをキャンセルする
   132:             //Enterキーを処理する
   133:             dgtEnter ();
   134:           } else {  //Shiftキーが押されている
   135:             ke.consume ();  //Enterキーをキャンセルする。デフォルトのShift+Enterの機能を無効化する
   136:             //改行を挿入する
   137:             dgtBoard.replaceRange ("\n", dgtBoard.getSelectionStart (), dgtBoard.getSelectionEnd ());
   138:           }
   139:         }
   140:       }
   141:     });
   142: 
   143:     //ポップアップメニュー
   144:     ActionListener popupActionListener = new ActionListener () {
   145:       @Override public void actionPerformed (ActionEvent ae) {
   146:         switch (ae.getActionCommand ()) {
   147:         case "Cut":
   148:           dgtCut ();
   149:           break;
   150:         case "Copy":
   151:           dgtCopy ();
   152:           break;
   153:         case "Paste":
   154:           dgtPaste ();
   155:           break;
   156:         case "Select All":
   157:           dgtSelectAll ();
   158:           break;
   159:         }
   160:       }
   161:     };
   162:     dgtPopupMenu = ComponentFactory.createPopupMenu (
   163:       dgtPopupCutMenuItem = Multilingual.mlnText (ComponentFactory.createMenuItem ("Cut", 'T', popupActionListener), "ja", "切り取り"),
   164:       dgtPopupCopyMenuItem = Multilingual.mlnText (ComponentFactory.createMenuItem ("Copy", 'C', popupActionListener), "ja", "コピー"),
   165:       dgtPopupPasteMenuItem = Multilingual.mlnText (ComponentFactory.createMenuItem ("Paste", 'P', popupActionListener), "ja", "貼り付け"),
   166:       ComponentFactory.createHorizontalSeparator (),
   167:       dgtPopupSelectAllMenuItem = Multilingual.mlnText (ComponentFactory.createMenuItem ("Select All", 'A', popupActionListener), "ja", "すべて選択")
   168:       );
   169:     dgtBoard.addMouseListener (new MouseAdapter () {
   170:       @Override public void mousePressed (MouseEvent me) {
   171:         dgtShowPopup (me);
   172:       }
   173:       @Override public void mouseReleased (MouseEvent me) {
   174:         dgtShowPopup (me);
   175:       }
   176:     });
   177: 
   178:     //ウインドウ
   179:     dgtFrame = Multilingual.mlnTitle (
   180:       ComponentFactory.createRestorableSubFrame (
   181:         Settings.SGS_DGT_FRAME_KEY,
   182:         "Console",
   183:         null,
   184:         dgtBoard
   185:         ),
   186:       "ja", "コンソール");
   187: 
   188:     dgtBoard.setCaretPosition (dgtOutputEnd);
   189: 
   190:   }  //dgtMake()
   191: 
   192:   //dgtShowPopup (me)
   193:   //  ポップアップメニューを表示する
   194:   //  テキストエリアのマウスリスナーが呼び出す
   195:   public static void dgtShowPopup (MouseEvent me) {
   196:     if (me.isPopupTrigger ()) {
   197:       //選択範囲があれば切り取りとコピーが有効
   198:       boolean enableCutAndCopy = XEiJ.clpClipboard != null && dgtBoard.getSelectionStart () != dgtBoard.getSelectionEnd ();
   199:       ComponentFactory.setEnabled (dgtPopupCutMenuItem, enableCutAndCopy);
   200:       ComponentFactory.setEnabled (dgtPopupCopyMenuItem, enableCutAndCopy);
   201:       //クリップボードに文字列があれば貼り付けが有効
   202:       ComponentFactory.setEnabled (dgtPopupPasteMenuItem, XEiJ.clpClipboard != null && XEiJ.clpClipboard.isDataFlavorAvailable (DataFlavor.stringFlavor));
   203:       //クリップボードがあればすべて選択が有効
   204:       ComponentFactory.setEnabled (dgtPopupSelectAllMenuItem, XEiJ.clpClipboard != null);
   205:       //ポップアップメニューを表示する
   206:       dgtPopupMenu.show (me.getComponent (), me.getX (), me.getY ());
   207:     }
   208:   }  //dgtShowPopup(MouseEvent)
   209: 
   210:   //dgtCut ()
   211:   //  切り取り
   212:   public static void dgtCut () {
   213:     if (XEiJ.clpClipboard != null) {
   214:       //選択範囲の文字列をコピーする
   215:       XEiJ.clpClipboardString = dgtBoard.getSelectedText ();
   216:       try {
   217:         XEiJ.clpClipboard.setContents (XEiJ.clpStringContents, XEiJ.clpClipboardOwner);
   218:         XEiJ.clpIsClipboardOwner = true;  //自分がコピーした
   219:       } catch (Exception e) {
   220:         return;
   221:       }
   222:       //選択範囲の文字列を削除する
   223:       dgtBoard.replaceRange ("", dgtBoard.getSelectionStart (), dgtBoard.getSelectionEnd ());
   224:     }
   225:   }  //dgtCut()
   226: 
   227:   //dgtCopy ()
   228:   //  コピー
   229:   public static void dgtCopy () {
   230:     if (XEiJ.clpClipboard != null) {
   231:       //選択範囲の文字列をコピーする
   232:       String selectedText = dgtBoard.getSelectedText ();
   233:       if (selectedText != null) {
   234:         XEiJ.clpClipboardString = selectedText;
   235:         try {
   236:           XEiJ.clpClipboard.setContents (XEiJ.clpStringContents, XEiJ.clpClipboardOwner);
   237:           XEiJ.clpIsClipboardOwner = true;  //自分がコピーした
   238:         } catch (Exception e) {
   239:           return;
   240:         }
   241:       }
   242:     }
   243:   }  //dgtCopy()
   244: 
   245:   //dgtPaste ()
   246:   //  貼り付け
   247:   public static void dgtPaste () {
   248:     if (XEiJ.clpClipboard != null) {
   249:       //クリップボードから文字列を取り出す
   250:       String string = null;
   251:       try {
   252:         string = (String) XEiJ.clpClipboard.getData (DataFlavor.stringFlavor);
   253:       } catch (Exception e) {
   254:         return;
   255:       }
   256:       //選択範囲の文字列を置換する
   257:       dgtBoard.replaceRange (string, dgtBoard.getSelectionStart (), dgtBoard.getSelectionEnd ());
   258:     }
   259:   }  //dgtPaste()
   260: 
   261:   //dgtSelectAll ()
   262:   //  すべて選択
   263:   public static void dgtSelectAll () {
   264:     if (XEiJ.clpClipboard != null) {
   265:       //すべて選択する
   266:       dgtBoard.selectAll ();
   267:     }
   268:   }  //dgtSelectAll()
   269: 
   270:   //dgtStart ()
   271:   public static void dgtStart () {
   272:     if (RestorableFrame.rfmGetOpened (Settings.SGS_DGT_FRAME_KEY)) {
   273:       dgtOpen ();
   274:     }
   275:   }  //dgtStart()
   276: 
   277:   //dgtOpen ()
   278:   //  デバッグコンソールを開く
   279:   public static void dgtOpen () {
   280:     if (dgtFrame == null) {
   281:       dgtMake ();
   282:     }
   283:     XEiJ.pnlExitFullScreen (false);
   284:     dgtFrame.setVisible (true);
   285:   }  //dgtOpen()
   286: 
   287:   //dgtPrintChar (c)
   288:   //  末尾に1文字追加する
   289:   public static void dgtPrintChar (int c) {
   290:     if (c == 0x08) {  //バックスペース
   291:       if (0 < dgtOutputEnd) {
   292:         if (dgtBoard != null) {
   293:           dgtBoard.replaceRange ("", dgtOutputEnd - 1, dgtOutputEnd);  //1文字削除
   294:           dgtOutputEnd--;
   295:           dgtBoard.setCaretPosition (dgtOutputEnd);
   296:         }
   297:       }
   298:     } else if (0x20 <= c && c != 0x7f || c == 0x09 || c == 0x0a) {  //タブと改行以外の制御コードを除く
   299:       if (dgtBoard != null) {
   300:         dgtBoard.insert (String.valueOf ((char) c), dgtOutputEnd);  //1文字追加
   301:         dgtOutputEnd++;
   302:         if (DGT_CUT_OUTPUT_LENGTH <= dgtOutputEnd) {
   303:           dgtBoard.replaceRange ("", 0, dgtOutputEnd - DGT_MAX_OUTPUT_LENGTH);  //先頭を削って短くする
   304:           dgtOutputEnd = DGT_MAX_OUTPUT_LENGTH;
   305:         }
   306:         dgtBoard.setCaretPosition (dgtOutputEnd);
   307:       }
   308:     }
   309:   }  //dgtPrintChar(int)
   310: 
   311:   //dgtPrint (s)
   312:   //  末尾に文字列を追加する
   313:   //  制御コードを処理しないのでタブと改行以外の制御コードを含めないこと
   314:   public static void dgtPrint (String s) {
   315:     if (s == null) {
   316:       return;
   317:     }
   318:     if (dgtFrame != null) {
   319:       dgtBoard.insert (s, dgtOutputEnd);  //文字列追加
   320:       dgtOutputEnd += s.length ();
   321:       if (DGT_CUT_OUTPUT_LENGTH <= dgtOutputEnd) {
   322:         dgtBoard.replaceRange ("", 0, dgtOutputEnd - DGT_MAX_OUTPUT_LENGTH);  //先頭を削って短くする
   323:         dgtOutputEnd = DGT_MAX_OUTPUT_LENGTH;
   324:       }
   325:       dgtBoard.setCaretPosition (dgtOutputEnd);
   326:     }
   327:   }  //dgtPrint(String)
   328: 
   329:   //dgtPrintln (s)
   330:   //  末尾に文字列と改行を追加する
   331:   //  制御コードを処理しないのでタブと改行以外の制御コードを含めないこと
   332:   public static void dgtPrintln (String s) {
   333:     dgtPrint (s);
   334:     dgtPrintChar ('\n');
   335:   }  //dgtPrintln(String)
   336: 
   337:   //dgtEnter ()
   338:   //  Enterキーを処理する
   339:   public static void dgtEnter () {
   340:     String text = dgtBoard.getText ();  //テキスト全体
   341:     int length = text.length ();  //テキスト全体の長さ
   342:     int outputLineStart = text.lastIndexOf ('\n', dgtOutputEnd - 1) + 1;  //出力の末尾の行の先頭。プロンプトの先頭
   343:     int caretLineStart = text.lastIndexOf ('\n', dgtBoard.getCaretPosition () - 1) + 1;  //キャレットがある行の先頭
   344:     if (outputLineStart <= caretLineStart) {  //出力の末尾の行の先頭以降でEnterキーが押された
   345:       dgtBoard.replaceRange ("", dgtOutputEnd, length);  //入力された文字列を一旦削除する
   346:       dgtSend (text.substring (dgtOutputEnd, length));  //入力された文字列を送信する
   347:     } else if (outputLineStart < dgtOutputEnd) {  //出力の末尾の行の先頭よりも手前でEnterキーが押されて、出力の末尾の行にプロンプトがあるとき
   348:       String prompt = text.substring (outputLineStart, dgtOutputEnd);  //出力の末尾の行のプロンプト
   349:       int caretLineEnd = text.indexOf ('\n', caretLineStart);  //キャレットがある行の末尾
   350:       if (caretLineEnd == -1) {
   351:         caretLineEnd = length;
   352:       }
   353:       String line = text.substring (caretLineStart, caretLineEnd);  //キャレットがある行
   354:       int start = line.indexOf (prompt);  //キャレットがある行のプロンプトの先頭
   355:       if (0 <= start) {  //キャレットがある行にプロンプトがあるとき
   356:         dgtOutputEnd = length;  //入力された文字列を無効化する
   357:         if (text.charAt (dgtOutputEnd - 1) != '\n' && !text.endsWith ("\n" + prompt)) {  //改行または改行+プロンプトで終わっていないとき
   358:           dgtBoard.insert ("\n", dgtOutputEnd);  //末尾に改行を追加する
   359:           dgtOutputEnd++;
   360:           if (DGT_CUT_OUTPUT_LENGTH <= dgtOutputEnd) {
   361:             dgtBoard.replaceRange ("", 0, dgtOutputEnd - DGT_MAX_OUTPUT_LENGTH);  //先頭を削って短くする
   362:             dgtOutputEnd = DGT_MAX_OUTPUT_LENGTH;
   363:           }
   364:         }
   365:         dgtBoard.setCaretPosition (dgtOutputEnd);
   366:         dgtSend (line.substring (start + prompt.length ()));  //プロンプトの後ろから行の末尾までを送信する
   367:       }
   368:     }
   369:   }  //dgtEnter()
   370: 
   371:   //dgtSend (s)
   372:   //  入力された文字列を処理する
   373:   public static void dgtSend (String s) {
   374:     dgtPrintln (s);
   375:     if (dgtInputMode == DGT_INPUT_MODE_COMMAND) {  //コマンドモード
   376:       ExpressionEvaluator.ExpressionElement nodeTree = XEiJ.fpuBox.evxParse (s, ExpressionEvaluator.EVM_COMMAND);
   377:       if (nodeTree != null) {
   378:         nodeTree.exlEval (ExpressionEvaluator.EVM_COMMAND);
   379:         if (nodeTree.exlValueType == ExpressionEvaluator.ElementType.ETY_FLOAT) {
   380:           dgtPrintln (nodeTree.exlFloatValue.toString ());
   381:         } else if (nodeTree.exlValueType == ExpressionEvaluator.ElementType.ETY_STRING) {
   382:           dgtPrintln (nodeTree.exlStringValue);
   383:         }
   384:       }
   385:     } else if (dgtInputMode == DGT_INPUT_MODE_PAGE) {  //ページモード
   386:       if (!(s.equals ("") ||
   387:             s.toLowerCase ().startsWith (" ") ||
   388:             s.toLowerCase ().startsWith ("y"))) {
   389:         dgtPageList = null;
   390:       }
   391:       dgtPrintPage ();
   392:     } else if (dgtInputMode == DGT_INPUT_MODE_ASSEMBLER) {  //アセンブラモード
   393:       if (s.equals (".")) {  //コマンドモードに戻る
   394:         dgtInputMode = DGT_INPUT_MODE_COMMAND;
   395:         dgtCurrentPrompt = DGT_COMMAND_PROMPT;
   396:       } else {  //アセンブルする
   397:         byte[] binary = Assembler.asmAssemble (dgtAssemblePC, s);
   398:         if (binary != null && 0 < binary.length) {  //バイナリがある
   399:           for (int i = 0; i < binary.length; i++) {
   400:             MC68060.mmuPokeByte (dgtAssemblePC + i, binary[i], dgtAssembleFC);
   401:           }
   402:           //逆アセンブルする
   403:           int itemAddress = dgtAssemblePC;
   404:           dgtAssemblePC += binary.length;
   405:           dgtMakeAssemblerPrompt ();
   406:           int supervisor = DebugConsole.dgtAssembleFC & 4;
   407:           StringBuilder sb = new StringBuilder ();
   408:           while (itemAddress < dgtAssemblePC) {
   409:             String code = Disassembler.disDisassemble (new StringBuilder (), itemAddress, supervisor).toString ();
   410:             int itemEndAddress = Disassembler.disPC;
   411:             if (dgtAssemblePC < itemEndAddress) {  //アセンブルした範囲からはみ出すときdc.wに置き換える
   412:               itemEndAddress = dgtAssemblePC;
   413:               StringBuilder sb2 = new StringBuilder ();
   414:               sb2.append ("dc.w    ");
   415:               for (int a = itemAddress; a < itemEndAddress; a += 2) {
   416:                 if (itemAddress < a) {
   417:                   sb2.append (',');
   418:                 }
   419:                 XEiJ.fmtHex4 (sb2.append ('$'), MC68060.mmuPeekWordZeroCode (a, supervisor));
   420:               }
   421:               code = sb2.toString ();
   422:             }
   423:             //1行目
   424:             int lineAddress = itemAddress;  //行の開始アドレス
   425:             int lineEndAddress = Math.min (lineAddress + 10, itemEndAddress);  //行の終了アドレス
   426:             //アドレス
   427:             XEiJ.fmtHex8 (sb, lineAddress).append ("  ");
   428:             //データ
   429:             for (int a = lineAddress; a < lineEndAddress; a += 2) {
   430:               XEiJ.fmtHex4 (sb, MC68060.mmuPeekWordZeroCode (a, supervisor));
   431:             }
   432:             sb.append (XEiJ.DBG_SPACES, 0, 2 * Math.max (0, lineAddress + 10 - lineEndAddress) + 2);
   433:             //逆アセンブル結果
   434:             sb.append (code).append ('\n');
   435:             //2行目以降
   436:             while (lineEndAddress < itemEndAddress) {
   437:               lineAddress = lineEndAddress;  //行の開始アドレス
   438:               lineEndAddress = Math.min (lineAddress + 10, itemEndAddress);  //行の終了アドレス
   439:               //アドレス
   440:               XEiJ.fmtHex8 (sb, lineAddress).append ("  ");
   441:               //データ
   442:               for (int a = lineAddress; a < lineEndAddress; a += 2) {
   443:                 XEiJ.fmtHex4 (sb, MC68060.mmuPeekWordZeroCode (a, supervisor));
   444:               }
   445:               sb.append ('\n');
   446:             }  //while
   447:             itemAddress = itemEndAddress;
   448:           }  //while itemAddress<dgtAssemblePC
   449:           dgtPrint (sb.toString ());
   450:         }  //if バイナリがある
   451:       }  //if コマンドモードに戻る/アセンブルする
   452:     }  //if コマンドモード/ページモード/アセンブラモード
   453:     if (dgtRequestRegs == 0) {
   454:       dgtPrintPrompt ();
   455:     }
   456:   }  //dgtSend(String)
   457: 
   458:   //dgtMakeAssemblerPrompt ()
   459:   //  アセンブラモードのプロンプトを作る
   460:   public static void dgtMakeAssemblerPrompt () {
   461:     StringBuilder sb = XEiJ.fmtHex8 (new StringBuilder (), dgtAssemblePC);
   462:     if (Model.MPU_MC68LC040 <= XEiJ.currentMPU) {
   463:       sb.append ('@').append (dgtAssembleFC);
   464:     }
   465:     dgtCurrentPrompt = sb.append ("  ").toString ();
   466:   }  //dgtMakeAssemblerPrompt()
   467: 
   468:   //dgtPrintPrompt (s)
   469:   //  プロンプトを表示する
   470:   //  既に表示されているときは何もしない
   471:   public static void dgtPrintPrompt () {
   472:     String text = dgtBoard.getText ();  //テキスト全体
   473:     if (!text.substring (text.lastIndexOf ('\n', dgtOutputEnd - 1) + 1, dgtOutputEnd).equals (dgtCurrentPrompt)) {  //プロンプトが表示されていない
   474:       dgtPrint (text.endsWith ("\n") ? dgtCurrentPrompt : "\n" + dgtCurrentPrompt);
   475:     }
   476:   }  //dgtPrintPrompt()
   477: 
   478:   //dgtPrintPage ()
   479:   //  ページを表示する
   480:   public static void dgtPrintPage () {
   481:     if (dgtPageList != null && !dgtPageList.isEmpty ()) {  //ページがある
   482:       dgtPrint (dgtPageList.pollFirst ());
   483:       if (!dgtPageList.isEmpty ()) {  //次のページがある
   484:         //ページモードに移行する
   485:         DebugConsole.dgtInputMode = DebugConsole.DGT_INPUT_MODE_PAGE;
   486:         dgtCurrentPrompt = DGT_PAGE_PROMPT;
   487:       }
   488:     }
   489:     if (dgtPageList == null || dgtPageList.isEmpty ()) {  //ページがない
   490:       dgtPageList = null;
   491:       //コマンドモードに戻る
   492:       dgtInputMode = DGT_INPUT_MODE_COMMAND;
   493:       dgtCurrentPrompt = DGT_COMMAND_PROMPT;
   494:     }
   495:     dgtPrintPrompt ();
   496:   }  //dgtPrintPage()
   497: 
   498: }  //class DebugConsole
   499: 
   500: 
   501: