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