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 * 1024;
26: public static final int DGT_CUT_OUTPUT_LENGTH = DGT_MAX_OUTPUT_LENGTH + 1024 * 64;
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:
52:
53:
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;
63: public static int dgtDisassembleFC;
64:
65:
66: public static int dgtDumpAddress;
67: public static int dgtDumpFunctionCode;
68: public static int dgtDumpStraddleChar;
69:
70:
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: }
94:
95:
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 &&
127: (modifiersEx & (InputEvent.ALT_DOWN_MASK |
128: InputEvent.CTRL_DOWN_MASK |
129: InputEvent.META_DOWN_MASK)) == 0) {
130: if ((modifiersEx & InputEvent.SHIFT_DOWN_MASK) == 0) {
131: ke.consume ();
132:
133: dgtEnter ();
134: } else {
135: ke.consume ();
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: }
191:
192:
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: }
209:
210:
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: }
226:
227:
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: }
244:
245:
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: }
260:
261:
262:
263: public static void dgtSelectAll () {
264: if (XEiJ.clpClipboard != null) {
265:
266: dgtBoard.selectAll ();
267: }
268: }
269:
270:
271: public static void dgtStart () {
272: if (RestorableFrame.rfmGetOpened (Settings.SGS_DGT_FRAME_KEY)) {
273: dgtOpen ();
274: }
275: }
276:
277:
278:
279: public static void dgtOpen () {
280: if (dgtFrame == null) {
281: dgtMake ();
282: }
283: XEiJ.pnlExitFullScreen (false);
284: dgtFrame.setVisible (true);
285: }
286:
287:
288:
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);
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);
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: }
310:
311:
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: }
328:
329:
330:
331:
332: public static void dgtPrintln (String s) {
333: dgtPrint (s);
334: dgtPrintChar ('\n');
335: }
336:
337:
338:
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) {
345: dgtBoard.replaceRange ("", dgtOutputEnd, length);
346: dgtSend (text.substring (dgtOutputEnd, length));
347: } else if (outputLineStart < dgtOutputEnd) {
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: }
370:
371:
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) {
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:
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:
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: }
447: itemAddress = itemEndAddress;
448: }
449: dgtPrint (sb.toString ());
450: }
451: }
452: }
453: if (dgtRequestRegs == 0) {
454: dgtPrintPrompt ();
455: }
456: }
457:
458:
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: }
467:
468:
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: }
477:
478:
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: }
497:
498: }
499:
500:
501: