DebugConsole.java
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13: package xeij;
14:
15: import java.awt.*;
16: import java.awt.datatransfer.*;
17: import java.awt.event.*;
18: import java.lang.*;
19: import java.util.*;
20: import javax.swing.*;
21: import javax.swing.event.*;
22:
23: public class DebugConsole {
24:
25: public static final int DGT_MAX_OUTPUT_LENGTH = 1024 * 64;
26: public static final int DGT_CUT_OUTPUT_LENGTH = DGT_MAX_OUTPUT_LENGTH + 1024 * 4;
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: public static boolean dgtRequestRegs;
51:
52:
53: public static int dgtAssemblePC;
54: public static int dgtAssembleFC;
55:
56:
57: public static int dgtDisassembleLastTail;
58: public static int dgtDisassemblePC;
59: public static int dgtDisassembleFC;
60:
61:
62: public static int dgtDumpAddress;
63: public static int dgtDumpFunctionCode;
64:
65:
66:
67: public static void dgtInit () {
68: dgtInputMode = DGT_INPUT_MODE_COMMAND;
69: dgtPageList = null;
70: dgtCurrentPrompt = DGT_COMMAND_PROMPT;
71: dgtFrame = null;
72: dgtBoard = null;
73: dgtPopupMenu = null;
74: dgtPopupCutMenuItem = null;
75: dgtPopupCopyMenuItem = null;
76: dgtPopupPasteMenuItem = null;
77: dgtPopupSelectAllMenuItem = null;
78: dgtOutputEnd = dgtCurrentPrompt.length ();
79: dgtRequestRegs = false;
80: dgtAssemblePC = 0;
81: dgtAssembleFC = 6;
82: dgtDisassembleLastTail = 0;
83: dgtDisassemblePC = 0;
84: dgtDisassembleFC = 6;
85: dgtDumpAddress = 0;
86: dgtDumpFunctionCode = 5;
87: }
88:
89:
90:
91:
92: public static void dgtMake () {
93:
94:
95: String initialText = (Multilingual.mlnJapanese ?
96: "[ h で使用法を表示]\n" :
97: "[enter h to display usage]\n") + dgtCurrentPrompt;
98: dgtOutputEnd = initialText.length ();
99: dgtBoard = ComponentFactory.createScrollTextArea (initialText, 500, 600, true);
100: dgtBoard.setUnderlineCursorOn (true);
101: dgtBoard.setLineWrap (true);
102: dgtBoard.addDocumentListener (new DocumentListener () {
103: @Override public void changedUpdate (DocumentEvent de) {
104: }
105: @Override public void insertUpdate (DocumentEvent de) {
106: if (de.getOffset () < dgtOutputEnd) {
107: dgtOutputEnd += de.getLength ();
108: }
109: }
110: @Override public void removeUpdate (DocumentEvent de) {
111: if (de.getOffset () < dgtOutputEnd) {
112: dgtOutputEnd -= Math.min (de.getLength (), dgtOutputEnd - de.getOffset ());
113: }
114: }
115: });
116: dgtBoard.addKeyListener (new KeyAdapter () {
117: @Override public void keyPressed (KeyEvent ke) {
118: int code = ke.getKeyCode ();
119: int modifiersEx = ke.getModifiersEx ();
120: if (code == KeyEvent.VK_ENTER &&
121: (modifiersEx & (InputEvent.ALT_DOWN_MASK |
122: InputEvent.CTRL_DOWN_MASK |
123: InputEvent.META_DOWN_MASK)) == 0) {
124: if ((modifiersEx & InputEvent.SHIFT_DOWN_MASK) == 0) {
125: ke.consume ();
126:
127: dgtEnter ();
128: } else {
129: ke.consume ();
130:
131: dgtBoard.replaceRange ("\n", dgtBoard.getSelectionStart (), dgtBoard.getSelectionEnd ());
132: }
133: }
134: }
135: });
136:
137:
138: ActionListener popupActionListener = new ActionListener () {
139: @Override public void actionPerformed (ActionEvent ae) {
140: switch (ae.getActionCommand ()) {
141: case "Cut":
142: dgtCut ();
143: break;
144: case "Copy":
145: dgtCopy ();
146: break;
147: case "Paste":
148: dgtPaste ();
149: break;
150: case "Select All":
151: dgtSelectAll ();
152: break;
153: }
154: }
155: };
156: dgtPopupMenu = ComponentFactory.createPopupMenu (
157: dgtPopupCutMenuItem = Multilingual.mlnText (ComponentFactory.createMenuItem ("Cut", 'T', popupActionListener), "ja", "切り取り"),
158: dgtPopupCopyMenuItem = Multilingual.mlnText (ComponentFactory.createMenuItem ("Copy", 'C', popupActionListener), "ja", "コピー"),
159: dgtPopupPasteMenuItem = Multilingual.mlnText (ComponentFactory.createMenuItem ("Paste", 'P', popupActionListener), "ja", "貼り付け"),
160: ComponentFactory.createHorizontalSeparator (),
161: dgtPopupSelectAllMenuItem = Multilingual.mlnText (ComponentFactory.createMenuItem ("Select All", 'A', popupActionListener), "ja", "すべて選択")
162: );
163: dgtBoard.addMouseListener (new MouseAdapter () {
164: @Override public void mousePressed (MouseEvent me) {
165: dgtShowPopup (me);
166: }
167: @Override public void mouseReleased (MouseEvent me) {
168: dgtShowPopup (me);
169: }
170: });
171:
172:
173: dgtFrame = Multilingual.mlnTitle (
174: ComponentFactory.createRestorableSubFrame (
175: Settings.SGS_DGT_FRAME_KEY,
176: "Console",
177: null,
178: dgtBoard
179: ),
180: "ja", "コンソール");
181:
182: dgtBoard.setCaretPosition (dgtOutputEnd);
183:
184: }
185:
186:
187:
188:
189: public static void dgtShowPopup (MouseEvent me) {
190: if (me.isPopupTrigger ()) {
191:
192: boolean enableCutAndCopy = XEiJ.clpClipboard != null && dgtBoard.getSelectionStart () != dgtBoard.getSelectionEnd ();
193: ComponentFactory.setEnabled (dgtPopupCutMenuItem, enableCutAndCopy);
194: ComponentFactory.setEnabled (dgtPopupCopyMenuItem, enableCutAndCopy);
195:
196: ComponentFactory.setEnabled (dgtPopupPasteMenuItem, XEiJ.clpClipboard != null && XEiJ.clpClipboard.isDataFlavorAvailable (DataFlavor.stringFlavor));
197:
198: ComponentFactory.setEnabled (dgtPopupSelectAllMenuItem, XEiJ.clpClipboard != null);
199:
200: dgtPopupMenu.show (me.getComponent (), me.getX (), me.getY ());
201: }
202: }
203:
204:
205:
206: public static void dgtCut () {
207: if (XEiJ.clpClipboard != null) {
208:
209: XEiJ.clpClipboardString = dgtBoard.getSelectedText ();
210: try {
211: XEiJ.clpClipboard.setContents (XEiJ.clpStringContents, XEiJ.clpClipboardOwner);
212: XEiJ.clpIsClipboardOwner = true;
213: } catch (Exception e) {
214: return;
215: }
216:
217: dgtBoard.replaceRange ("", dgtBoard.getSelectionStart (), dgtBoard.getSelectionEnd ());
218: }
219: }
220:
221:
222:
223: public static void dgtCopy () {
224: if (XEiJ.clpClipboard != null) {
225:
226: String selectedText = dgtBoard.getSelectedText ();
227: if (selectedText != null) {
228: XEiJ.clpClipboardString = selectedText;
229: try {
230: XEiJ.clpClipboard.setContents (XEiJ.clpStringContents, XEiJ.clpClipboardOwner);
231: XEiJ.clpIsClipboardOwner = true;
232: } catch (Exception e) {
233: return;
234: }
235: }
236: }
237: }
238:
239:
240:
241: public static void dgtPaste () {
242: if (XEiJ.clpClipboard != null) {
243:
244: String string = null;
245: try {
246: string = (String) XEiJ.clpClipboard.getData (DataFlavor.stringFlavor);
247: } catch (Exception e) {
248: return;
249: }
250:
251: dgtBoard.replaceRange (string, dgtBoard.getSelectionStart (), dgtBoard.getSelectionEnd ());
252: }
253: }
254:
255:
256:
257: public static void dgtSelectAll () {
258: if (XEiJ.clpClipboard != null) {
259:
260: dgtBoard.selectAll ();
261: }
262: }
263:
264:
265: public static void dgtStart () {
266: if (RestorableFrame.rfmGetOpened (Settings.SGS_DGT_FRAME_KEY)) {
267: dgtOpen ();
268: }
269: }
270:
271:
272:
273: public static void dgtOpen () {
274: if (dgtFrame == null) {
275: dgtMake ();
276: }
277: dgtFrame.setVisible (true);
278: }
279:
280:
281:
282: public static void dgtPrintChar (int c) {
283: if (c == 0x08) {
284: if (0 < dgtOutputEnd) {
285: if (dgtBoard != null) {
286: dgtBoard.replaceRange ("", dgtOutputEnd - 1, dgtOutputEnd);
287: dgtOutputEnd--;
288: dgtBoard.setCaretPosition (dgtOutputEnd);
289: }
290: }
291: } else if (0x20 <= c && c != 0x7f || c == 0x09 || c == 0x0a) {
292: if (dgtBoard != null) {
293: dgtBoard.insert (String.valueOf ((char) c), dgtOutputEnd);
294: dgtOutputEnd++;
295: if (DGT_CUT_OUTPUT_LENGTH <= dgtOutputEnd) {
296: dgtBoard.replaceRange ("", 0, dgtOutputEnd - DGT_MAX_OUTPUT_LENGTH);
297: dgtOutputEnd = DGT_MAX_OUTPUT_LENGTH;
298: }
299: dgtBoard.setCaretPosition (dgtOutputEnd);
300: }
301: }
302: }
303:
304:
305:
306:
307: public static void dgtPrint (String s) {
308: if (s == null) {
309: return;
310: }
311: if (dgtFrame != null) {
312: dgtBoard.insert (s, dgtOutputEnd);
313: dgtOutputEnd += s.length ();
314: if (DGT_CUT_OUTPUT_LENGTH <= dgtOutputEnd) {
315: dgtBoard.replaceRange ("", 0, dgtOutputEnd - DGT_MAX_OUTPUT_LENGTH);
316: dgtOutputEnd = DGT_MAX_OUTPUT_LENGTH;
317: }
318: dgtBoard.setCaretPosition (dgtOutputEnd);
319: }
320: }
321:
322:
323:
324:
325: public static void dgtPrintln (String s) {
326: dgtPrint (s);
327: dgtPrintChar ('\n');
328: }
329:
330:
331:
332: public static void dgtEnter () {
333: String text = dgtBoard.getText ();
334: int length = text.length ();
335: int outputLineStart = text.lastIndexOf ('\n', dgtOutputEnd - 1) + 1;
336: int caretLineStart = text.lastIndexOf ('\n', dgtBoard.getCaretPosition () - 1) + 1;
337: if (outputLineStart <= caretLineStart) {
338: dgtBoard.replaceRange ("", dgtOutputEnd, length);
339: dgtSend (text.substring (dgtOutputEnd, length));
340: } else if (outputLineStart < dgtOutputEnd) {
341: String prompt = text.substring (outputLineStart, dgtOutputEnd);
342: int caretLineEnd = text.indexOf ('\n', caretLineStart);
343: if (caretLineEnd == -1) {
344: caretLineEnd = length;
345: }
346: String line = text.substring (caretLineStart, caretLineEnd);
347: int start = line.indexOf (prompt);
348: if (0 <= start) {
349: dgtOutputEnd = length;
350: if (text.charAt (dgtOutputEnd - 1) != '\n' && !text.endsWith ("\n" + prompt)) {
351: dgtBoard.insert ("\n", dgtOutputEnd);
352: dgtOutputEnd++;
353: if (DGT_CUT_OUTPUT_LENGTH <= dgtOutputEnd) {
354: dgtBoard.replaceRange ("", 0, dgtOutputEnd - DGT_MAX_OUTPUT_LENGTH);
355: dgtOutputEnd = DGT_MAX_OUTPUT_LENGTH;
356: }
357: }
358: dgtBoard.setCaretPosition (dgtOutputEnd);
359: dgtSend (line.substring (start + prompt.length ()));
360: }
361: }
362: }
363:
364:
365:
366: public static void dgtSend (String s) {
367: dgtPrintln (s);
368: if (dgtInputMode == DGT_INPUT_MODE_COMMAND) {
369: ExpressionEvaluator.ExpressionElement nodeTree = XEiJ.fpuBox.evxParse (s, ExpressionEvaluator.EVM_COMMAND);
370: if (nodeTree != null) {
371: nodeTree.exlEval (ExpressionEvaluator.EVM_COMMAND);
372: if (nodeTree.exlValueType == ExpressionEvaluator.ElementType.ETY_FLOAT) {
373: dgtPrintln (nodeTree.exlFloatValue.toString ());
374: } else if (nodeTree.exlValueType == ExpressionEvaluator.ElementType.ETY_STRING) {
375: dgtPrintln (nodeTree.exlStringValue);
376: }
377: }
378: } else if (dgtInputMode == DGT_INPUT_MODE_PAGE) {
379: if (!(s.equals ("") ||
380: s.toLowerCase ().startsWith (" ") ||
381: s.toLowerCase ().startsWith ("y"))) {
382: dgtPageList = null;
383: }
384: dgtPrintPage ();
385: } else if (dgtInputMode == DGT_INPUT_MODE_ASSEMBLER) {
386: if (s.equals (".")) {
387: dgtInputMode = DGT_INPUT_MODE_COMMAND;
388: dgtCurrentPrompt = DGT_COMMAND_PROMPT;
389: } else {
390: byte[] binary = Assembler.asmAssemble (dgtAssemblePC, s);
391: if (binary != null && 0 < binary.length) {
392: for (int i = 0; i < binary.length; i++) {
393: MC68060.mmuPokeByte (dgtAssemblePC + i, binary[i], dgtAssembleFC);
394: }
395:
396: int itemAddress = dgtAssemblePC;
397: dgtAssemblePC += binary.length;
398: dgtMakeAssemblerPrompt ();
399: int supervisor = DebugConsole.dgtAssembleFC & 4;
400: StringBuilder sb = new StringBuilder ();
401: while (itemAddress < dgtAssemblePC) {
402: String code = Disassembler.disDisassemble (new StringBuilder (), itemAddress, supervisor).toString ();
403: int itemEndAddress = Disassembler.disPC;
404: if (dgtAssemblePC < itemEndAddress) {
405: itemEndAddress = dgtAssemblePC;
406: StringBuilder sb2 = new StringBuilder ();
407: sb2.append ("dc.w ");
408: for (int a = itemAddress; a < itemEndAddress; a += 2) {
409: if (itemAddress < a) {
410: sb2.append (',');
411: }
412: XEiJ.fmtHex4 (sb2.append ('$'), MC68060.mmuPeekWordZeroCode (a, supervisor));
413: }
414: code = sb2.toString ();
415: }
416:
417: int lineAddress = itemAddress;
418: int lineEndAddress = Math.min (lineAddress + 10, itemEndAddress);
419:
420: XEiJ.fmtHex8 (sb, lineAddress).append (" ");
421:
422: for (int a = lineAddress; a < lineEndAddress; a += 2) {
423: XEiJ.fmtHex4 (sb, MC68060.mmuPeekWordZeroCode (a, supervisor));
424: }
425: sb.append (XEiJ.DBG_SPACES, 0, 2 * Math.max (0, lineAddress + 10 - lineEndAddress) + 2);
426:
427: sb.append (code).append ('\n');
428:
429: while (lineEndAddress < itemEndAddress) {
430: lineAddress = lineEndAddress;
431: lineEndAddress = Math.min (lineAddress + 10, itemEndAddress);
432:
433: XEiJ.fmtHex8 (sb, lineAddress).append (" ");
434:
435: for (int a = lineAddress; a < lineEndAddress; a += 2) {
436: XEiJ.fmtHex4 (sb, MC68060.mmuPeekWordZeroCode (a, supervisor));
437: }
438: sb.append ('\n');
439: }
440: itemAddress = itemEndAddress;
441: }
442: dgtPrint (sb.toString ());
443: }
444: }
445: }
446: if (!dgtRequestRegs) {
447: dgtPrintPrompt ();
448: }
449: }
450:
451:
452:
453: public static void dgtMakeAssemblerPrompt () {
454: StringBuilder sb = XEiJ.fmtHex8 (new StringBuilder (), dgtAssemblePC);
455: if (Model.MPU_MC68LC040 <= XEiJ.currentMPU) {
456: sb.append ('@').append (dgtAssembleFC);
457: }
458: dgtCurrentPrompt = sb.append (" ").toString ();
459: }
460:
461:
462:
463:
464: public static void dgtPrintPrompt () {
465: String text = dgtBoard.getText ();
466: if (!text.substring (text.lastIndexOf ('\n', dgtOutputEnd - 1) + 1, dgtOutputEnd).equals (dgtCurrentPrompt)) {
467: dgtPrint (text.endsWith ("\n") ? dgtCurrentPrompt : "\n" + dgtCurrentPrompt);
468: }
469: }
470:
471:
472:
473: public static void dgtPrintPage () {
474: if (dgtPageList != null && !dgtPageList.isEmpty ()) {
475: dgtPrint (dgtPageList.pollFirst ());
476: if (!dgtPageList.isEmpty ()) {
477:
478: DebugConsole.dgtInputMode = DebugConsole.DGT_INPUT_MODE_PAGE;
479: dgtCurrentPrompt = DGT_PAGE_PROMPT;
480: }
481: }
482: if (dgtPageList == null || dgtPageList.isEmpty ()) {
483: dgtPageList = null;
484:
485: dgtInputMode = DGT_INPUT_MODE_COMMAND;
486: dgtCurrentPrompt = DGT_COMMAND_PROMPT;
487: }
488: dgtPrintPrompt ();
489: }
490:
491: }
492:
493:
494: