MemoryDumpList.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.event.*;
17: import java.lang.*;
18: import java.util.*;
19: import javax.swing.*;
20: import javax.swing.event.*;
21: import javax.swing.text.*;
22:
23: public class MemoryDumpList {
24:
25: public static final int DMP_ITEM_SIZE = 0x00000010;
26: public static final int DMP_PAGE_SIZE = 0x00000400;
27: public static final int DMP_ITEM_MASK = -DMP_ITEM_SIZE;
28: public static final int DMP_PAGE_MASK = -DMP_PAGE_SIZE;
29: public static final int DMP_MAX_ITEMS = DMP_PAGE_SIZE / DMP_ITEM_SIZE + 2;
30:
31: public static final char[] DMP_BASE = (
32:
33:
34: "xxxxxxxx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx ").toCharArray ();
35: public static final int DMP_DATA_START = 10;
36: public static final int[] DMP_DATA_ADDRESS = {
37: 0, 1, -1, 2, 3, -1, 4, 5, -1, 6, 7, -1, -1,
38: 8, 9, -1, 10, 11, -1, 12, 13, -1, 14, 15, -1, -1,
39: 16, 17, -1, 18, 19, -1, 20, 21, -1, 22, 23, -1, -1,
40: 24, 25, -1, 26, 27, -1, 28, 29, -1, 30, 31,
41: };
42: public static final int[] DMP_DATA_OFFSET = {
43: 0, 1, 3, 4, 6, 7, 9, 10,
44: 13, 14, 16, 17, 19, 20, 22, 23,
45: 26, 27, 29, 30, 32, 33, 35, 36,
46: 39, 40, 42, 43, 45, 46, 48, 49,
47: };
48:
49: public static int dmpItemCount;
50: public static int dmpItemIndex;
51: public static int dmpPageAddress;
52: public static final int[] dmpAddressArray = new int[DMP_MAX_ITEMS];
53: public static final int[] dmpSplitArray = new int[DMP_MAX_ITEMS];
54: public static final int[] dmpCaretArray = new int[DMP_MAX_ITEMS];
55:
56: public static JFrame dmpFrame;
57: public static ScrollTextArea dmpBoard;
58: public static JTextArea dmpTextArea;
59: public static Hex8Spinner dmpSpinner;
60:
61: public static int dmpSupervisorMode;
62: public static JCheckBox dmpSupervisorCheckBox;
63: public static boolean dmpSecondBridge;
64: public static Color dmpCellophaneColor;
65:
66:
67:
68: public static void dmpInit () {
69:
70: dmpItemCount = 0;
71: dmpItemIndex = 0;
72: dmpPageAddress = 0;
73: dmpSupervisorMode = 1;
74:
75:
76:
77:
78: dmpFrame = null;
79:
80: }
81:
82:
83: public static void dmpStart () {
84: if (RestorableFrame.rfmGetOpened (Settings.SGS_DMP_FRAME_KEY)) {
85: dmpOpen (-1, -1, true);
86: }
87: }
88:
89:
90:
91:
92: public static void dmpOpen (int address, int supervisor, boolean forceUpdate) {
93: if (dmpFrame == null) {
94: dmpMake ();
95: }
96: dmpUpdate (address, supervisor, forceUpdate);
97: dmpFrame.setVisible (true);
98: XEiJ.dbgVisibleMask |= XEiJ.DBG_DMP_VISIBLE_MASK;
99: }
100:
101: static class MemoryDumpTextArea extends ScrollTextArea {
102: @Override public void paintAfterText (JTextArea textArea, Graphics2D g2) {
103: if (MemoryDumpList.dmpSecondBridge) {
104: try {
105: g2.setPaint (MemoryDumpList.dmpCellophaneColor);
106: Rectangle r0 = textArea.modelToView2D (61).getBounds ();
107: Rectangle r1 = textArea.modelToView2D (62).getBounds ();
108: g2.fillRect (r0.x - (r1.x - r0.x), r0.y,
109: r1.x - r0.x, r0.height * DMP_MAX_ITEMS);
110: g2.fillRect (r0.x + (r1.x - r0.x) * 16, r0.y,
111: r1.x - r0.x, r0.height * DMP_MAX_ITEMS);
112: } catch (BadLocationException ble) {
113: }
114: }
115: }
116: }
117:
118:
119:
120: public static void dmpMake () {
121:
122:
123: dmpBoard = ComponentFactory.setPreferredSize (
124: ComponentFactory.setFont (new MemoryDumpTextArea (), LnF.lnfMonospacedFont),
125: 500, 400);
126: dmpBoard.setMargin (new Insets (2, 4, 2, 4));
127: dmpBoard.setHighlightCursorOn (true);
128: dmpTextArea = dmpBoard.getTextArea ();
129: dmpTextArea.setEditable (false);
130:
131:
132: dmpSpinner = new Hex8Spinner (dmpPageAddress, DMP_ITEM_MASK, true);
133:
134:
135:
136:
137:
138: dmpSpinner.addChangeListener (new ChangeListener () {
139: @Override public void stateChanged (ChangeEvent ce) {
140: if (XEiJ.dbgEventMask == 0) {
141: dmpUpdate (dmpSpinner.getIntValue (), dmpSupervisorMode, false);
142: }
143: }
144: });
145:
146:
147:
148:
149:
150:
151: ComponentFactory.addListener (
152: dmpTextArea,
153: new CaretListener () {
154: @Override public void caretUpdate (CaretEvent ce) {
155: if (XEiJ.dbgEventMask == 0) {
156: int p = ce.getDot ();
157: if (p == ce.getMark ()) {
158: int i = Arrays.binarySearch (dmpSplitArray, 1, dmpItemCount, p + 1);
159: i = (i >> 31 ^ i) - 1;
160: dmpSpinner.setHintIndex (i);
161: }
162: }
163: }
164: });
165:
166:
167: ComponentFactory.addListener (
168: dmpTextArea,
169: new MouseAdapter () {
170: @Override public void mousePressed (MouseEvent me) {
171: if (XEiJ.mpuTask == null && me.isPopupTrigger ()) {
172: XEiJ.dbgShowPopup (me, dmpTextArea, false);
173: }
174: }
175: @Override public void mouseReleased (MouseEvent me) {
176: if (XEiJ.mpuTask == null && me.isPopupTrigger ()) {
177: XEiJ.dbgShowPopup (me, dmpTextArea, false);
178: }
179: }
180: });
181:
182:
183: ComponentFactory.addListener (
184: dmpBoard,
185: new FocusAdapter () {
186: @Override public void focusGained (FocusEvent fe) {
187: dmpBoard.setCaretVisible (true);
188: }
189: @Override public void focusLost (FocusEvent fe) {
190: dmpBoard.setCaretVisible (false);
191: }
192: });
193:
194:
195: ComponentFactory.addListener (
196: dmpBoard,
197: new KeyAdapter () {
198: @Override public void keyTyped (KeyEvent ke) {
199: if (XEiJ.dbgEventMask == 0) {
200: int x = Character.digit (ke.getKeyChar (), 16);
201: if (x >= 0) {
202: int p = dmpTextArea.getCaretPosition ();
203: int i = Arrays.binarySearch (dmpSplitArray, 1, dmpItemCount, p + 1);
204: i = (i >> 31 ^ i) - 1;
205: int t = p - dmpCaretArray[i] - DMP_DATA_START;
206: if (t >= 0 && t < DMP_DATA_ADDRESS.length) {
207: t = DMP_DATA_ADDRESS[t];
208: if (t >= 0) {
209: int a = dmpAddressArray[i] + (t >> 1);
210: XEiJ.dbgEventMask++;
211: if ((t & 1) == 0) {
212: try {
213: MC68060.mmuPokeByteData (a, x << 4 | Character.digit (dmpTextArea.getText (p + 1, 1).charAt (0), 16), XEiJ.regSRS);
214: } catch (BadLocationException ble) {
215: }
216: dmpTextArea.replaceRange (XEiJ.fmtHex2 (MC68060.mmuPeekByteZeroData (a, XEiJ.regSRS)), p, p + 2);
217: dmpTextArea.setCaretPosition (p + 1);
218: } else {
219: try {
220: MC68060.mmuPokeByteData (a, Character.digit (dmpTextArea.getText (p - 1, 1).charAt (0), 16) << 4 | x, XEiJ.regSRS);
221: } catch (BadLocationException ble) {
222: }
223: dmpTextArea.replaceRange (XEiJ.fmtHex2 (MC68060.mmuPeekByteZeroData (a, XEiJ.regSRS)), p - 1, p + 1);
224: if (t < 31) {
225: dmpTextArea.setCaretPosition (dmpCaretArray[i] + DMP_DATA_START + DMP_DATA_OFFSET[t + 1]);
226: }
227: }
228: XEiJ.dbgEventMask--;
229: }
230: }
231: }
232: }
233: }
234: });
235:
236:
237: ActionListener listener = new ActionListener () {
238: @Override public void actionPerformed (ActionEvent ae) {
239: Object source = ae.getSource ();
240: switch (ae.getActionCommand ()) {
241: case "Reload":
242: dmpItemCount = 0;
243: dmpUpdate (dmpAddressArray[dmpItemIndex], dmpSupervisorMode, true);
244: break;
245: case "User/Supervisor":
246: if (XEiJ.dbgEventMask == 0) {
247: dmpUpdate (dmpAddressArray[dmpItemIndex], ((JCheckBox) ae.getSource ()).isSelected () ? 1 : 0, true);
248: }
249: break;
250: case "Second bridge":
251: dmpSecondBridge = ((JCheckBox) ae.getSource ()).isSelected ();
252: dmpItemCount = 0;
253: dmpUpdate (dmpAddressArray[dmpItemIndex], dmpSupervisorMode, true);
254: break;
255: }
256: }
257: };
258:
259:
260: JButton reloadButton =
261: Multilingual.mlnToolTipText (
262: ComponentFactory.createImageButton (
263: XEiJ.createImage (
264: 20, 14,
265: "11111111111111111111" +
266: "1..................1" +
267: "1.......1111.......1" +
268: "1......111111.1....1" +
269: "1.....11....111....1" +
270: "1....11.....111....1" +
271: "1....11....1111....1" +
272: "1....11............1" +
273: "1....11............1" +
274: "1.....11....11.....1" +
275: "1......111111......1" +
276: "1.......1111.......1" +
277: "1..................1" +
278: "11111111111111111111",
279: LnF.lnfRGB[0],
280: LnF.lnfRGB[12]),
281: "Reload", listener),
282: "ja", "再読み込み");
283:
284:
285: dmpSupervisorCheckBox =
286: Multilingual.mlnToolTipText (
287: ComponentFactory.createIconCheckBox (
288: dmpSupervisorMode != 0,
289: XEiJ.createImage (
290: 20, 14,
291: "22222222222222222222" +
292: "2..................2" +
293: "2..................2" +
294: "2.....11....11.....2" +
295: "2.....11....11.....2" +
296: "2.....11....11.....2" +
297: "2.....11....11.....2" +
298: "2.....11....11.....2" +
299: "2.....11....11.....2" +
300: "2.....11111111.....2" +
301: "2.....11111111.....2" +
302: "2..................2" +
303: "2..................2" +
304: "22222222222222222222",
305: LnF.lnfRGB[0],
306: LnF.lnfRGB[12],
307: LnF.lnfRGB[12]),
308: XEiJ.createImage (
309: 20, 14,
310: "22222222222222222222" +
311: "2..................2" +
312: "2..................2" +
313: "2.....11111111.....2" +
314: "2.....11111111.....2" +
315: "2.....11...........2" +
316: "2.....11111111.....2" +
317: "2.....11111111.....2" +
318: "2...........11.....2" +
319: "2.....11111111.....2" +
320: "2.....11111111.....2" +
321: "2..................2" +
322: "2..................2" +
323: "22222222222222222222",
324: LnF.lnfRGB[0],
325: LnF.lnfRGB[12],
326: LnF.lnfRGB[12]),
327: "User/Supervisor", listener),
328: "ja", "ユーザ/スーパーバイザ");
329:
330:
331: dmpSecondBridge = false;
332: dmpCellophaneColor = new Color ((LnF.lnfRGB[5] & 0x00ffffff) | 0xcc000000, true);
333: JCheckBox secondBridgeCheckBox =
334: Multilingual.mlnToolTipText (
335: ComponentFactory.createIconCheckBox (
336: dmpSecondBridge,
337: XEiJ.createImage (
338: 20, 14,
339: "22222222222222222222" +
340: "2..................2" +
341: "2...........11111..2" +
342: "2...........11111..2" +
343: "2....111111111111..2" +
344: "2...........11111..2" +
345: "2...........11111..2" +
346: "2..................2" +
347: "2..................2" +
348: "2....1111111111....2" +
349: "2..................2" +
350: "2..................2" +
351: "2..................2" +
352: "22222222222222222222",
353: LnF.lnfRGB[0],
354: LnF.lnfRGB[12],
355: LnF.lnfRGB[12]),
356: XEiJ.createImage (
357: 20, 14,
358: "22222222222222222222" +
359: "2..................2" +
360: "2...........11111..2" +
361: "2...........11111..2" +
362: "2....111111111111..2" +
363: "2...........11111..2" +
364: "2...........11111..2" +
365: "2..11111...........2" +
366: "2..11111...........2" +
367: "2..111111111111....2" +
368: "2..11111...........2" +
369: "2..11111...........2" +
370: "2..................2" +
371: "22222222222222222222",
372: LnF.lnfRGB[0],
373: LnF.lnfRGB[12],
374: LnF.lnfRGB[12]),
375: "Second bridge", listener),
376: "ja", "セカンドブリッジ");
377:
378:
379: dmpFrame = Multilingual.mlnTitle (
380: ComponentFactory.createRestorableSubFrame (
381: Settings.SGS_DMP_FRAME_KEY,
382: "Memory dump list",
383: null,
384: ComponentFactory.createBorderPanel (
385: dmpBoard,
386: ComponentFactory.createHorizontalBox (
387: dmpSpinner,
388: reloadButton,
389: dmpSupervisorCheckBox,
390: secondBridgeCheckBox,
391: Box.createHorizontalGlue ()
392: )
393: )
394: ),
395: "ja", "メモリダンプリスト");
396: ComponentFactory.addListener (
397: dmpFrame,
398: new WindowAdapter () {
399: @Override public void windowClosing (WindowEvent we) {
400: XEiJ.dbgVisibleMask &= ~XEiJ.DBG_DMP_VISIBLE_MASK;
401: }
402: });
403:
404: }
405:
406:
407:
408: public static void dmpUpdate (int address, int supervisor, boolean forceUpdate) {
409:
410: XEiJ.dbgEventMask++;
411:
412: if (address == -1) {
413: address = XEiJ.regRn[15];
414: forceUpdate = true;
415: }
416:
417: if (supervisor == -1) {
418: supervisor = XEiJ.regSRS;
419: forceUpdate = true;
420: }
421:
422: if ((dmpSupervisorMode != 0) != (supervisor != 0)) {
423: dmpSupervisorMode = supervisor;
424: forceUpdate = true;
425: if (dmpSupervisorCheckBox.isSelected () != (supervisor != 0)) {
426: dmpSupervisorCheckBox.setSelected (supervisor != 0);
427: }
428: }
429:
430: if (forceUpdate) {
431: dmpItemCount = 0;
432: }
433:
434: if (dmpItemCount != 0) {
435: int i = Arrays.binarySearch (dmpAddressArray, 1, dmpItemCount, address + 1);
436: i = (i >> 31 ^ i) - 1;
437: if (0 < i && i < dmpItemCount - 1 &&
438: dmpAddressArray[i] == address) {
439:
440:
441:
442: if (dmpItemIndex != i) {
443: dmpItemIndex = i;
444: dmpTextArea.setCaretPosition (dmpCaretArray[i]);
445: }
446:
447: XEiJ.dbgEventMask--;
448:
449: return;
450: }
451: }
452:
453:
454:
455:
456:
457: address &= DMP_ITEM_MASK;
458: dmpPageAddress = address & DMP_PAGE_MASK;
459: int pageEndAddress = dmpPageAddress + DMP_PAGE_SIZE;
460:
461:
462: dmpAddressArray[0] = dmpPageAddress - DMP_ITEM_SIZE;
463: dmpSplitArray[0] = 0;
464: dmpCaretArray[0] = 0;
465: StringBuilder sb = new StringBuilder (
466:
467:
468:
469: "▲ +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +A +B +C +D +E +F 0123456789ABCDEF\n");
470: int itemCount = 1;
471: int itemAddress = dmpPageAddress;
472: boolean bridge = false;
473: for (int k = 1; k <= 200; k++) {
474: int h = MC68060.mmuPeekByteZeroData (itemAddress - k, supervisor);
475: if ((0x81 <= h && h <= 0x9f) ||
476: (0xe0 <= h && h <= 0xef)) {
477: bridge = !bridge;
478: } else {
479: break;
480: }
481: }
482:
483: do {
484: int itemEndAddress = itemAddress + DMP_ITEM_SIZE;
485:
486: if (itemAddress == address) {
487: dmpItemIndex = itemCount;
488: }
489: dmpAddressArray[itemCount] = itemAddress;
490: dmpSplitArray[itemCount] = sb.length ();
491: dmpCaretArray[itemCount] = sb.length ();
492:
493: XEiJ.fmtHex8 (DMP_BASE, 0, itemAddress);
494:
495: XEiJ.fmtHex2 (DMP_BASE, 10, MC68060.mmuPeekByteZeroData (itemAddress , supervisor));
496: XEiJ.fmtHex2 (DMP_BASE, 13, MC68060.mmuPeekByteZeroData (itemAddress + 1, supervisor));
497: XEiJ.fmtHex2 (DMP_BASE, 16, MC68060.mmuPeekByteZeroData (itemAddress + 2, supervisor));
498: XEiJ.fmtHex2 (DMP_BASE, 19, MC68060.mmuPeekByteZeroData (itemAddress + 3, supervisor));
499: XEiJ.fmtHex2 (DMP_BASE, 23, MC68060.mmuPeekByteZeroData (itemAddress + 4, supervisor));
500: XEiJ.fmtHex2 (DMP_BASE, 26, MC68060.mmuPeekByteZeroData (itemAddress + 5, supervisor));
501: XEiJ.fmtHex2 (DMP_BASE, 29, MC68060.mmuPeekByteZeroData (itemAddress + 6, supervisor));
502: XEiJ.fmtHex2 (DMP_BASE, 32, MC68060.mmuPeekByteZeroData (itemAddress + 7, supervisor));
503: XEiJ.fmtHex2 (DMP_BASE, 36, MC68060.mmuPeekByteZeroData (itemAddress + 8, supervisor));
504: XEiJ.fmtHex2 (DMP_BASE, 39, MC68060.mmuPeekByteZeroData (itemAddress + 9, supervisor));
505: XEiJ.fmtHex2 (DMP_BASE, 42, MC68060.mmuPeekByteZeroData (itemAddress + 10, supervisor));
506: XEiJ.fmtHex2 (DMP_BASE, 45, MC68060.mmuPeekByteZeroData (itemAddress + 11, supervisor));
507: XEiJ.fmtHex2 (DMP_BASE, 49, MC68060.mmuPeekByteZeroData (itemAddress + 12, supervisor));
508: XEiJ.fmtHex2 (DMP_BASE, 52, MC68060.mmuPeekByteZeroData (itemAddress + 13, supervisor));
509: XEiJ.fmtHex2 (DMP_BASE, 55, MC68060.mmuPeekByteZeroData (itemAddress + 14, supervisor));
510: XEiJ.fmtHex2 (DMP_BASE, 58, MC68060.mmuPeekByteZeroData (itemAddress + 15, supervisor));
511: sb.append (DMP_BASE);
512:
513: boolean nextBridge = false;
514: int a;
515: if (!bridge) {
516: sb.append (' ');
517: a = itemAddress;
518: } else if (itemAddress == dmpPageAddress ||
519: dmpSecondBridge) {
520: a = itemAddress - 1;
521: } else {
522: sb.append (" ");
523: a = itemAddress + 1;
524: }
525: for (; a < itemEndAddress; a++) {
526: int h = MC68060.mmuPeekByteZeroData (a, supervisor);
527: int c;
528: if ((0x81 <= h && h <= 0x9f) ||
529: (0xe0 <= h && h <= 0xef)) {
530: int l = MC68060.mmuPeekByteZeroData (a + 1, supervisor);
531: if (0x40 <= l && l <= 0xfc && l != 0x7f) {
532: c = CharacterCode.chrSJISToChar[h << 8 | l];
533: if (c == 0) {
534: c = '※';
535: } else if (c == 0x3000) {
536: c = '\u2b1a';
537: }
538: a++;
539: if (a == itemEndAddress) {
540: nextBridge = true;
541: }
542: } else {
543: c = '.';
544: }
545: } else {
546: c = CharacterCode.chrSJISToChar[h];
547: if (c < 0x20 || c == 0x7f) {
548: c = '.';
549: }
550: }
551: sb.append ((char) c);
552: }
553: sb.append ('\n');
554:
555: itemCount++;
556: itemAddress = itemEndAddress;
557: bridge = nextBridge;
558: } while (itemAddress < pageEndAddress);
559:
560:
561: dmpAddressArray[itemCount] = itemAddress;
562: dmpSplitArray[itemCount] = sb.length ();
563: dmpCaretArray[itemCount] = sb.length ();
564: sb.append (
565:
566:
567: "▼ +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +A +B +C +D +E +F 0123456789ABCDEF");
568: itemCount++;
569: dmpItemCount = itemCount;
570:
571:
572: dmpTextArea.setText (sb.toString ());
573: dmpTextArea.setCaretPosition (dmpCaretArray[dmpItemIndex]);
574:
575:
576: dmpSpinner.setHintArray (dmpAddressArray, itemCount);
577: dmpSpinner.setHintIndex (dmpItemIndex);
578:
579: XEiJ.dbgEventMask--;
580:
581: }
582:
583: }
584:
585:
586: