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