SpritePatternViewer.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.awt.font.*;
18: import java.awt.geom.*;
19: import java.awt.image.*;
20: import java.util.*;
21: import javax.swing.*;
22:
23: public class SpritePatternViewer {
24:
25: public static final boolean SPV_ON = true;
26:
27:
28: static final int SPV_CELL_WIDTH = 36;
29: static final int SPV_CELL_HEIGHT = 36;
30:
31:
32:
33: static final int SPV_GROUP_GAP = 4;
34:
35:
36: static final String SPV_FONT_NAME = "Dialog";
37: static final int SPV_FONT_STYLE = Font.BOLD;
38: static final int SPV_FONT_SIZE = 16;
39: static final int SPV_HEADER_WIDTH = SPV_FONT_SIZE * 3;
40: static final int SPV_HEADER_HEIGHT = SPV_FONT_SIZE;
41:
42:
43: static int spvImageWidth;
44: static int spvImageHeight;
45: static BufferedImage spvBufferedImage;
46: static int[] spvBitmap;
47: static ScrollCanvas spvCanvas;
48:
49:
50: static final int SPV_BACKGROUND_RGB = 0xff333333;
51: static final int SPV_FOREGROUND_RGB = 0xffcccccc;
52: static final int SPV_GRAY_LINE_RGB = 0xff999999;
53: static final int SPV_BLOCK_DOT_RGB = 0xffffffff;
54:
55:
56:
57:
58: static final int SPV_DEF_BANK = 0;
59: static final int SPV_MIN_BANK = 0;
60: static final int SPV_MAX_BANK = 20;
61: static int spvBankNumber;
62: static JComboBox<String> spvBankComboBox;
63: static int spvCellOffset;
64: static int spvColsBit;
65: static int spvRowsBit;
66: static int spvColsMask;
67: static int spvRowsMask;
68: static int spvWidth;
69: static int spvHeight;
70:
71:
72:
73:
74: static final int SPV_DEF_SIZE = -1;
75: static final int SPV_MIN_SIZE = -1;
76: static final int SPV_MAX_SIZE = 1;
77: static final int SPV_LAST_SIZE = 1;
78: static int spvSizeNumber;
79: static JComboBox<String> spvSizeComboBox;
80: static final int[] spvLastSizeArray = new int[4096];
81: static final int[] spvSizeArray = new int[4096];
82:
83:
84:
85:
86: static final int SPV_DEF_BLOCK = -1;
87: static final int SPV_MIN_BLOCK = -1;
88: static final int SPV_MAX_BLOCK = 15;
89: static final int SPV_LAST_BLOCK = 1;
90: static int spvBlockNumber;
91: static JComboBox<String> spvBlockComboBox;
92: static final int[] spvLastBlockArray = new int[4 * 4096];
93: static final int[] spvBlockArray = new int[4 * 4096];
94:
95:
96:
97:
98: static final int SPV_DEF_FLIP = -1;
99: static final int SPV_MIN_FLIP = -1;
100: static final int SPV_MAX_FLIP = 3;
101: static final int SPV_LAST_FLIP = 0;
102: static int spvFlipNumber;
103: static JComboBox<String> spvFlipComboBox;
104: static final int[] spvLastFlipArray = new int[4 * 4096];
105: static final int[] spvFlipArray = new int[4 * 4096];
106:
107:
108:
109:
110: static final int SPV_DEF_SCALE = 0;
111: static final int SPV_MIN_SCALE = -1;
112: static final int SPV_MAX_SCALE = 4;
113: static int spvScaleNumber;
114: static JComboBox<String> spvScaleComboBox;
115:
116:
117:
118:
119: static final boolean SPV_DEF_HEX = false;
120: static boolean spvHex;
121:
122:
123: static boolean spvStopped;
124: static boolean spvStoppedRequest;
125:
126: static final short[] spvCopiedNum = new short[SpriteScreen.SPR_COUNT];
127: static final short[] spvCopiedCol = new short[SpriteScreen.SPR_COUNT];
128: static final byte[] spvCopiedPrw = new byte[SpriteScreen.SPR_COUNT];
129: static final boolean[] spvCopiedH = new boolean[SpriteScreen.SPR_COUNT];
130: static final boolean[] spvCopiedV = new boolean[SpriteScreen.SPR_COUNT];
131: static final int[] spvCopiedPat = new int[32 * 4096];
132: static final short[] spvCopiedTNum = new short[4096 * 4];
133: static final short[] spvCopiedTCol = new short[4096 * 4];
134: static final boolean[] spvCopiedTH = new boolean[4096 * 4];
135: static final boolean[] spvCopiedTV = new boolean[4096 * 4];
136: static final int[] spvCopiedPalTbl = new int[65536];
137: static final int[] spvCopiedPal16TS = new int[256];
138:
139: static short[] spvNum;
140: static short[] spvCol;
141: static byte[] spvPrw;
142: static boolean[] spvH;
143: static boolean[] spvV;
144: static int[] spvPat;
145: static short[] spvTNum;
146: static short[] spvTCol;
147: static boolean[] spvTH;
148: static boolean[] spvTV;
149: static int[] spvPalTbl;
150: static int[] spvPal16TS;
151:
152: static final int[] spvPal32TS = new int[256];
153:
154:
155: static JTextField spvTextField;
156: static boolean spvTextLocked;
157:
158:
159: static JFrame spvFrame;
160:
161:
162: static JPopupMenu spvPopupMenu;
163: static int spvOffsetToCopy;
164: static int spvLengthToCopy;
165:
166:
167: public static final int SPV_INTERVAL = 10;
168: public static int spvTimer;
169:
170:
171:
172: public static void spvInit () {
173:
174: spvBankNumber = Settings.sgsGetInt ("spvbank", SPV_DEF_BANK, SPV_MIN_BANK, SPV_MAX_BANK);
175: spvBlockNumber = Settings.sgsGetInt ("spvblock", SPV_DEF_BLOCK, SPV_MIN_BLOCK, SPV_MAX_BLOCK);
176: spvFlipNumber = Settings.sgsGetInt ("spvflip", SPV_DEF_FLIP, SPV_MIN_FLIP, SPV_MAX_FLIP);
177: spvHex = Settings.sgsGetOnOff ("spvhex", SPV_DEF_HEX);
178: spvScaleNumber = Settings.sgsGetInt ("spvscale", SPV_DEF_SCALE, SPV_MIN_SCALE, SPV_MAX_SCALE);
179: spvSizeNumber = Settings.sgsGetInt ("spvsize", SPV_DEF_SIZE, SPV_MIN_SIZE, SPV_MAX_SIZE);
180:
181: spvImageWidth = (SPV_HEADER_WIDTH +
182: (SPV_CELL_WIDTH << 6) +
183: (SPV_GROUP_GAP << (6 - 2)) - SPV_GROUP_GAP);
184: spvImageHeight = (SPV_HEADER_HEIGHT +
185: (SPV_CELL_HEIGHT << 6) +
186: (SPV_GROUP_GAP << (6 - 2)) - SPV_GROUP_GAP);
187:
188: spvSetBankNumber (spvBankNumber);
189:
190: Arrays.fill (spvLastSizeArray, SPV_LAST_SIZE);
191:
192: Arrays.fill (spvLastBlockArray, SPV_LAST_BLOCK);
193:
194: Arrays.fill (spvLastFlipArray, SPV_LAST_FLIP);
195:
196: spvSetStoppedOff ();
197:
198: spvFrame = null;
199:
200: spvTimer = 0;
201: }
202:
203:
204:
205: public static void spvTini () {
206:
207: Settings.sgsPutInt ("spvbank", spvBankNumber);
208: Settings.sgsPutInt ("spvblock", spvBlockNumber);
209: Settings.sgsPutInt ("spvflip", spvFlipNumber);
210: Settings.sgsPutOnOff ("spvhex", spvHex);
211: Settings.sgsPutInt ("spvscale", spvScaleNumber);
212: Settings.sgsPutInt ("spvsize", spvSizeNumber);
213: }
214:
215:
216:
217: static void spvSetBankNumber (int number) {
218: spvBankNumber = number;
219: spvCellOffset = (spvBankNumber < 16 ? spvBankNumber << 8 :
220: spvBankNumber < 20 ? (spvBankNumber - 16) << 10 :
221: 0);
222: spvColsBit =
223: spvRowsBit = (spvBankNumber < 16 ? 4 :
224: spvBankNumber < 20 ? 5 :
225: 6);
226: spvColsMask =
227: spvRowsMask = (1 << spvRowsBit) - 1;
228: spvWidth = (SPV_HEADER_WIDTH +
229: (SPV_CELL_WIDTH << spvColsBit) +
230: (SPV_GROUP_GAP << (spvColsBit - 2)) - SPV_GROUP_GAP);
231: spvHeight = (SPV_HEADER_HEIGHT +
232: (SPV_CELL_HEIGHT << spvRowsBit) +
233: (SPV_GROUP_GAP << (spvRowsBit - 2)) - SPV_GROUP_GAP);
234: if (spvCanvas != null) {
235: spvDrawHeader ();
236: spvCanvas.setImage (spvWidth, spvHeight);
237: }
238: }
239:
240:
241:
242: static int spvColToX (int col) {
243: int g = col >> 2;
244: col &= 3;
245: return (SPV_HEADER_WIDTH +
246: ((SPV_CELL_WIDTH << 2) + SPV_GROUP_GAP) * g +
247: SPV_CELL_WIDTH * col);
248: }
249:
250:
251:
252: static int spvRowToY (int row) {
253: int g = row >> 2;
254: row &= 3;
255: return (SPV_HEADER_HEIGHT +
256: ((SPV_CELL_HEIGHT << 2) + SPV_GROUP_GAP) * g +
257: SPV_CELL_HEIGHT * row);
258: }
259:
260:
261:
262: static int spvXToXCol (int x) {
263: if (x < 0 || spvWidth <= x) {
264: return -1;
265: }
266: if (x < SPV_HEADER_WIDTH) {
267: return -1;
268: }
269: x -= SPV_HEADER_WIDTH;
270: int g = x / ((SPV_CELL_WIDTH << 2) + SPV_GROUP_GAP);
271: x -= ((SPV_CELL_WIDTH << 2) + SPV_GROUP_GAP) * g;
272: if ((SPV_CELL_WIDTH << 2) <= x) {
273: return -1;
274: }
275: int col = x / SPV_CELL_WIDTH;
276: x -= SPV_CELL_WIDTH * col;
277: return (x << 16) | ((g << 2) + col);
278: }
279:
280:
281:
282: static int spvYToYRow (int y) {
283: if (y < 0 || spvHeight <= y) {
284: return -1;
285: }
286: if (y < SPV_HEADER_HEIGHT) {
287: return -1;
288: }
289: y -= SPV_HEADER_HEIGHT;
290: int g = y / ((SPV_CELL_HEIGHT << 2) + SPV_GROUP_GAP);
291: y -= ((SPV_CELL_HEIGHT << 2) + SPV_GROUP_GAP) * g;
292: if ((SPV_CELL_HEIGHT << 2) <= y) {
293: return -1;
294: }
295: int row = y / SPV_CELL_HEIGHT;
296: y -= SPV_CELL_HEIGHT * row;
297: return (y << 16) | ((g << 2) + row);
298: }
299:
300:
301:
302: public static void spvStart () {
303: if (RestorableFrame.rfmGetOpened (Settings.SGS_SPV_FRAME_KEY)) {
304: spvOpen ();
305: }
306: }
307:
308:
309:
310: public static void spvOpen () {
311: if (spvFrame == null) {
312: spvMakeFrame ();
313: } else {
314: spvUpdateFrame ();
315: }
316: XEiJ.dbgVisibleMask |= XEiJ.DBG_SPV_VISIBLE_MASK;
317: XEiJ.pnlExitFullScreen (false);
318: spvFrame.setVisible (true);
319: }
320:
321:
322:
323:
324: static void spvMakeFrame () {
325:
326: spvBufferedImage = new BufferedImage (spvImageWidth, spvImageHeight, BufferedImage.TYPE_INT_ARGB);
327: spvDrawHeader ();
328:
329: spvBitmap = ((DataBufferInt) spvBufferedImage.getRaster ().getDataBuffer ()).getData ();
330:
331: spvCanvas = new ScrollCanvas (spvBufferedImage, spvWidth, spvHeight);
332: spvCanvas.setMatColor (new Color (SPV_BACKGROUND_RGB));
333: spvCanvas.setMinScaleShift (SPV_MIN_SCALE);
334: spvCanvas.setMaxScaleShift (SPV_MAX_SCALE);
335: spvCanvas.setScaleShift (spvScaleNumber);
336:
337: ActionListener listener = new ActionListener () {
338: @Override public void actionPerformed (ActionEvent ae) {
339: Object source = ae.getSource ();
340: String command = ae.getActionCommand ();
341: switch (command) {
342: case "Bank":
343: spvSetBankNumber (spvBankComboBox.getSelectedIndex () + SPV_MIN_BANK);
344: if (XEiJ.mpuTask == null) {
345: spvUpdateFrame ();
346: }
347: break;
348: case "Size":
349: spvSizeNumber = spvSizeComboBox.getSelectedIndex () + SPV_MIN_SIZE;
350: if (XEiJ.mpuTask == null) {
351: spvUpdateFrame ();
352: }
353: break;
354: case "Block":
355: spvBlockNumber = spvBlockComboBox.getSelectedIndex () + SPV_MIN_BLOCK;
356: if (XEiJ.mpuTask == null) {
357: spvUpdateFrame ();
358: }
359: break;
360: case "Flip":
361: spvFlipNumber = spvFlipComboBox.getSelectedIndex () + SPV_MIN_FLIP;
362: if (XEiJ.mpuTask == null) {
363: spvUpdateFrame ();
364: }
365: break;
366: case "Hex":
367: spvHex = (((JCheckBox) source).isSelected ());
368: spvDrawHeader ();
369: spvUpdateFrame ();
370: break;
371: case "Stop":
372: spvStoppedRequest = (((JCheckBox) source).isSelected ());
373: if (XEiJ.mpuTask == null) {
374: spvUpdateFrame ();
375: }
376: break;
377: case "Scale":
378: spvCanvas.setScaleShift (spvScaleComboBox.getSelectedIndex () + SPV_MIN_SCALE);
379: break;
380: case "Copy as hexadecimal":
381: spvCopyPattern ();
382: break;
383: default:
384: System.out.println ("unknown action command " + command);
385: }
386: }
387: };
388:
389: spvTextField = new JTextField ();
390: spvTextField.setEditable (false);
391: spvTextField.setHorizontalAlignment (JTextField.CENTER);
392:
393: spvFrame = Multilingual.mlnTitle (
394: ComponentFactory.createRestorableSubFrame (
395: Settings.SGS_SPV_FRAME_KEY,
396: "Sprite Pattern Viewer",
397: null,
398: ComponentFactory.createBorderPanel (
399: 0, 0,
400:
401: spvCanvas,
402:
403: ComponentFactory.createVerticalBox (
404:
405: ComponentFactory.createHorizontalBox (
406: Box.createHorizontalGlue (),
407:
408: Multilingual.mlnText (
409: ComponentFactory.createLabel ("Bank "),
410: "ja", "バンク "),
411: spvBankComboBox = ComponentFactory.createComboBox (
412: spvBankNumber - SPV_MIN_BANK,
413: "Bank",
414: listener,
415: "0", "1", "2", "3", "4", "5", "6", "7", "8",
416: "9", "10", "11", "12", "13", "14", "15",
417: "0-3", "4-7", "8-11", "12-15", "0-15"),
418:
419: Multilingual.mlnText (
420: ComponentFactory.createLabel ("Size "),
421: "ja", "サイズ "),
422: spvSizeComboBox = ComponentFactory.createComboBox (
423: spvSizeNumber - SPV_MIN_SIZE,
424: "Size",
425: listener,
426: 4,
427: Multilingual.mlnJapanese ? "自動" : "Auto",
428: "8x8", "16x16"),
429:
430: Multilingual.mlnText (
431: ComponentFactory.createLabel ("Block "),
432: "ja", "ブロック "),
433: spvBlockComboBox = ComponentFactory.createComboBox (
434: spvBlockNumber - SPV_MIN_BLOCK,
435: "Block",
436: listener,
437: 4,
438: Multilingual.mlnJapanese ? "自動" : "Auto",
439: "0", "1", "2", "3", "4", "5", "6", "7", "8",
440: "9", "10", "11", "12", "13", "14", "15"),
441:
442: Multilingual.mlnText (
443: ComponentFactory.createLabel ("Flip "),
444: "ja", "反転 "),
445: spvFlipComboBox = ComponentFactory.createComboBox (
446: spvFlipNumber - SPV_MIN_FLIP,
447: "Flip",
448: listener,
449: 4,
450: Multilingual.mlnJapanese ? "自動" : "Auto",
451: Multilingual.mlnJapanese ? "なし" : "-",
452: Multilingual.mlnJapanese ? "左右" : "H",
453: Multilingual.mlnJapanese ? "上下" : "V",
454: Multilingual.mlnJapanese ? "上下左右" : "H&V"),
455:
456: Box.createHorizontalStrut (5),
457: ComponentFactory.createCheckBox (spvHex, "Hex", listener),
458:
459: Box.createHorizontalGlue ()
460: ),
461:
462: ComponentFactory.createHorizontalBox (
463:
464: spvTextField,
465:
466: Multilingual.mlnText (
467: ComponentFactory.createLabel ("Scale "),
468: "ja", "倍率 "),
469: spvScaleComboBox = ComponentFactory.createComboBox (
470: spvCanvas.getScaleShift () - SPV_MIN_SCALE,
471: "Scale",
472: listener,
473: "1", "2", "4", "8", "16", "32"),
474:
475: Box.createHorizontalStrut (5),
476: Multilingual.mlnText (
477: ComponentFactory.createCheckBox (spvStoppedRequest, "Stop", listener),
478: "ja", "停止")
479:
480: )
481: )
482: )
483: ),
484: "ja", "スプライトパターンビュア");
485:
486: spvCanvas.addScaleShiftListener (new ScrollCanvas.ScaleShiftListener () {
487: @Override public void scaleShiftChanged (int scaleShift) {
488: spvScaleComboBox.setSelectedIndex (scaleShift - SPV_MIN_SCALE);
489: }
490: });
491:
492: ComponentFactory.addListener (
493: spvFrame,
494: new WindowAdapter () {
495: @Override public void windowClosing (WindowEvent we) {
496: XEiJ.dbgVisibleMask &= ~XEiJ.DBG_SPV_VISIBLE_MASK;
497: }
498: });
499:
500: spvPopupMenu = ComponentFactory.createPopupMenu (
501: Multilingual.mlnText (
502: ComponentFactory.createMenuItem ("Copy as hexadecimal", 'C', listener),
503: "ja", "16進数でコピー")
504: );
505:
506: MouseAdapter ma = new MouseAdapter () {
507: @Override public void mouseClicked (MouseEvent me) {
508: spvTextLocked = !spvTextLocked;
509: }
510: @Override public void mouseMoved (MouseEvent me) {
511: if (!spvTextLocked) {
512: MouseEvent2D me2D = (MouseEvent2D) me;
513: int x = (int) me2D.getX2D ();
514: int y = (int) me2D.getY2D ();
515: String s = spvGetPixel (x, y);
516: spvTextField.setText (s == null ? "" : s);
517: }
518: }
519: @Override public void mousePressed (MouseEvent me) {
520: spvShowPopup (me);
521: }
522: @Override public void mouseReleased (MouseEvent me) {
523: spvShowPopup (me);
524: }
525: };
526: spvCanvas.addMouseListener (ma);
527: spvCanvas.addMouseMotionListener (ma);
528: }
529:
530:
531:
532: static void spvDrawHeader () {
533: Graphics2D g2 = spvBufferedImage.createGraphics ();
534:
535: g2.setColor (new Color (SPV_BACKGROUND_RGB));
536: g2.fillRect (0, 0, spvWidth, spvHeight);
537:
538: g2.setColor (new Color (SPV_FOREGROUND_RGB));
539: g2.setFont (new Font (SPV_FONT_NAME, SPV_FONT_STYLE, SPV_FONT_SIZE));
540:
541: for (int col = 0; col <= spvColsMask; col++) {
542: spvDrawString (g2,
543: spvColToX (col) + SPV_CELL_WIDTH / 2,
544: spvRowToY (0) - SPV_FONT_SIZE / 12,
545: String.format (spvHex ? "%X" : "%d",
546: col & spvColsMask),
547: SwingConstants.SOUTH);
548: }
549:
550: for (int row = 0; row <= spvRowsMask; row++) {
551: spvDrawString (g2,
552: spvColToX (0) - SPV_FONT_SIZE / 6,
553: spvRowToY (row) + SPV_CELL_HEIGHT / 2,
554: String.format (spvHex ? "%X" : "%d",
555: spvCellOffset + ((row & spvRowsMask) << spvColsBit)),
556: SwingConstants.EAST);
557: }
558: }
559:
560:
561:
562: static void spvDrawString (Graphics2D g2, int x, int y, String s, int d) {
563: Font f = g2.getFont ();
564: FontRenderContext flc = g2.getFontRenderContext ();
565: TextLayout tl = new TextLayout (s, f, flc);
566: Rectangle2D r = tl.getBounds ();
567: int rx = (int) Math.round (r.getX ());
568: int ry = (int) Math.round (r.getY ());
569: int rw = (int) Math.round (r.getWidth ());
570: int rh = (int) Math.round (r.getHeight ());
571: switch (d) {
572: case SwingConstants.NORTH_WEST:
573: g2.drawString (s, x - rx, y - ry);
574: break;
575: case SwingConstants.NORTH:
576: g2.drawString (s, x - (rx + (rw >> 1)), y - ry);
577: break;
578: case SwingConstants.NORTH_EAST:
579: g2.drawString (s, x - (rx + rw), y - ry);
580: break;
581: case SwingConstants.WEST:
582: g2.drawString (s, x - rx, y - (ry + (rh >> 1)));
583: break;
584: case SwingConstants.CENTER:
585: g2.drawString (s, x - (rx + (rw >> 1)), y - (ry + (rh >> 1)));
586: break;
587: case SwingConstants.EAST:
588: g2.drawString (s, x - (rx + rw), y - (ry + (rh >> 1)));
589: break;
590: case SwingConstants.SOUTH_WEST:
591: g2.drawString (s, x - rx, y - (ry + rh));
592: break;
593: case SwingConstants.SOUTH:
594: g2.drawString (s, x - (rx + (rw >> 1)), y - (ry + rh));
595: break;
596: case SwingConstants.SOUTH_EAST:
597: g2.drawString (s, x - (rx + rw), y - (ry + rh));
598: break;
599: }
600: }
601:
602:
603:
604: static void spvShowPopup (MouseEvent me) {
605: if (me.isPopupTrigger ()) {
606: MouseEvent2D me2D = (MouseEvent2D) me;
607: int x = (int) me2D.getX2D ();
608: int y = (int) me2D.getY2D ();
609: if (spvGetPatternToCopy (x, y)) {
610: Point p = spvCanvas.getPopupPoint (me2D);
611: spvPopupMenu.show (spvCanvas, p.x, p.y);
612: }
613: }
614: }
615:
616:
617:
618:
619: static boolean spvGetPatternToCopy (int x, int y) {
620: int col = spvXToXCol (x);
621: int row = spvYToYRow (y);
622: if (col < 0 || row < 0) {
623: spvOffsetToCopy = 0;
624: spvLengthToCopy = 0;
625: return false;
626: }
627: x = col >> 16;
628: y = row >> 16;
629: col = (char) col;
630: row = (char) row;
631: int n = (spvCellOffset + col + (row << spvColsBit)) << 2;
632: int size = spvSizeArray[n >> 2];
633: if (size < 0) {
634: size = spvLastSizeArray[n >> 2];
635: }
636: if (size == 0) {
637: int qCol = x / (SPV_CELL_WIDTH / 2);
638: int qRow = y / (SPV_CELL_HEIGHT / 2);
639: n += qRow + (qCol << 1);
640: spvLengthToCopy = 1 << 3;
641: } else {
642: spvLengthToCopy = 4 << 3;
643: }
644: spvOffsetToCopy = n << 3;
645: return true;
646: }
647:
648:
649:
650: static void spvCopyPattern () {
651: if (spvLengthToCopy != 0) {
652: StringBuilder sb = new StringBuilder ();
653: for (int i = 0; i < spvLengthToCopy; i++) {
654: sb.append (String.format ("%08X\n", spvPat[spvOffsetToCopy + i]));
655: }
656: XEiJ.clpCopy (sb.toString ());
657: }
658: }
659:
660:
661:
662: static String spvGetPixel (int x, int y) {
663: int col = spvXToXCol (x);
664: int row = spvYToYRow (y);
665: if (col < 0 || row < 0) {
666: return null;
667: }
668: x = col >> 16;
669: y = row >> 16;
670: col = (char) col;
671: row = (char) row;
672: int n = (spvCellOffset + col + (row << spvColsBit)) << 2;
673: int size = spvSizeArray[n >> 2];
674: if (size < 0) {
675: size = spvLastSizeArray[n >> 2];
676: }
677: if (size == 0) {
678: int qCol = x / (SPV_CELL_WIDTH / 2);
679: int qRow = y / (SPV_CELL_HEIGHT / 2);
680: n += qRow + (qCol << 1);
681: x -= (SPV_CELL_WIDTH / 2) * qCol;
682: y -= (SPV_CELL_HEIGHT / 2) * qRow;
683: x -= 1;
684: y -= 1;
685: if (x < 0 || 2 * 8 <= x ||
686: y < 0 || 2 * 8 <= y) {
687: return null;
688: }
689: x >>= 1;
690: y >>= 1;
691: int pb = spvBlockArray[n];
692: if (pb < 0) {
693: pb = spvLastBlockArray[n];
694: }
695: int vh = spvFlipArray[n];
696: if (vh < 0) {
697: vh = spvLastFlipArray[n];
698: }
699: int v = vh >> 1;
700: int h = vh & 1;
701: if (h != 0) {
702: x ^= 7;
703: }
704: if (v != 0) {
705: y ^= 7;
706: }
707: int pc = (spvPat[(n << 3) + y] >> ((7 - x) << 2)) & 15;
708: int p = pb << 4 | pc;
709: int c = spvPal16TS[p];
710: return String.format ("8x8 n=%d x=%d y=%d p=0x%02X c=0x%04X(%d,%d,%d,%d)",
711: n, x, y, p, c,
712: c >> 11, (c >> 6) & 31, (c >> 1) & 31, c & 1);
713: } else {
714: x -= 2;
715: y -= 2;
716: if (x < 0 || 2 * 16 <= x ||
717: y < 0 || 2 * 16 <= y) {
718: return null;
719: }
720: x >>= 1;
721: y >>= 1;
722: int pb = spvBlockArray[n];
723: if (pb < 0) {
724: pb = spvLastBlockArray[n];
725: }
726: int vh = spvFlipArray[n];
727: if (vh < 0) {
728: vh = spvLastFlipArray[n];
729: }
730: int v = vh >> 1;
731: int h = vh & 1;
732: if ((vh & 1) != 0) {
733: x ^= 15;
734: }
735: if ((vh & 2) != 0) {
736: y ^= 15;
737: }
738: int pc = (spvPat[(n << 3) + y + ((x & 8) << 1)] >> ((7 - (x & 7)) << 2)) & 15;
739: int p = pb << 4 | pc;
740: int c = spvPal16TS[p];
741: return String.format ("16x16 n=%d x=%d y=%d p=0x%02X c=0x%04X(%d,%d,%d,%d)",
742: n >> 2, x, y, p, c,
743: c >> 11, (c >> 6) & 31, (c >> 1) & 31, c & 1);
744: }
745: }
746:
747:
748:
749: static void spvUpdateFrame () {
750: if (spvFrame == null) {
751: return;
752: }
753:
754: if (spvStopped != spvStoppedRequest) {
755: if (spvStoppedRequest) {
756: spvSetStoppedOn ();
757: } else {
758: spvSetStoppedOff ();
759: }
760: }
761:
762: for (int i = 0; i < 256; i++) {
763: spvPal32TS[i] = spvPalTbl[spvPal16TS[i]];
764: }
765:
766: Arrays.fill (spvSizeArray, spvSizeNumber);
767: Arrays.fill (spvBlockArray, spvBlockNumber);
768: Arrays.fill (spvFlipArray, spvFlipNumber);
769:
770: if (spvSizeNumber < 0 ||
771: spvBlockNumber < 0 ||
772: spvFlipNumber < 0) {
773:
774: for (int sn = 0; sn < SpriteScreen.sprNumberOfSprites; sn++) {
775: if ((256 <= sn && sn < 256 + 8) ||
776: spvPrw[sn] == 0) {
777: continue;
778: }
779: int n = spvNum[sn] << 2;
780: if (spvSizeArray[n >> 2] < 0) {
781: spvSizeArray[n >> 2] =
782: spvLastSizeArray[n >> 2] = 1;
783: }
784: int pb = spvCol[sn] >> 4;
785: int vh = ((spvV[sn] ? 2 : 0) |
786: (spvH[sn] ? 1 : 0));
787: for (int k = 0; k < 4; k++) {
788: if (spvBlockArray[n + k] < 0) {
789: spvBlockArray[n + k] =
790: spvLastBlockArray[n + k] = pb;
791: }
792: if (spvFlipArray[n + k] < 0) {
793: spvFlipArray[n + k] =
794: spvLastFlipArray[n + k] = vh;
795: }
796: }
797: }
798:
799: int tm = 0;
800: if ((SpriteScreen.sprReg4BgCtrlPort & 1) != 0) {
801: tm |= 1 << ((SpriteScreen.sprReg4BgCtrlPort >> 1) & 3);
802: }
803: if (((SpriteScreen.sprReg8ResoPort & 3) == 0 ||
804: SpriteScreen.spr512bg1) &&
805: (SpriteScreen.sprReg4BgCtrlPort & 8) != 0) {
806: tm |= 1 << ((SpriteScreen.sprReg4BgCtrlPort >> 4) & 3);
807: }
808: if ((SpriteScreen.sprReg8ResoPort & 3) == 0) {
809: for (int tp = 0; tp < 4; tp++) {
810: if ((tm & (1 << tp)) == 0) {
811: continue;
812: }
813: int o = 4096 * tp;
814: for (int i = 0; i < 4096; i++) {
815: int n = spvTNum[o + i] >> 3;
816: if (spvSizeArray[n >> 2] < 0) {
817: spvSizeArray[n >> 2] =
818: spvLastSizeArray[n >> 2] = 0;
819: }
820: int pb = spvTCol[o + i] >> 4;
821: int vh = ((spvTV[o + i] ? 2 : 0) |
822: (spvTH[o + i] ? 1 : 0));
823: if (spvBlockArray[n] < 0) {
824: spvBlockArray[n] =
825: spvLastBlockArray[n] = pb;
826: }
827: if (spvFlipArray[n] < 0) {
828: spvFlipArray[n] =
829: spvLastFlipArray[n] = vh;
830: }
831: }
832: }
833: } else {
834: for (int tp = 0; tp < 4; tp++) {
835: if ((tm & (1 << tp)) == 0) {
836: continue;
837: }
838: int o = 4096 * tp;
839: for (int i = 0; i < 4096; i++) {
840: int n = spvTNum[o + i] >> 1;
841: if (spvSizeArray[n >> 2] < 0) {
842: spvSizeArray[n >> 2] =
843: spvLastSizeArray[n >> 2] = 1;
844: }
845: int pb = spvTCol[o + i] >> 4;
846: int vh = ((spvTV[o + i] ? 2 : 0) |
847: (spvTH[o + i] ? 1 : 0));
848: for (int k = 0; k < 4; k++) {
849: if (spvBlockArray[n + k] < 0) {
850: spvBlockArray[n + k] =
851: spvLastBlockArray[n + k] = pb;
852: }
853: if (spvFlipArray[n + k] < 0) {
854: spvFlipArray[n + k] =
855: spvLastFlipArray[n + k] = vh;
856: }
857: }
858: }
859: }
860: }
861:
862: for (int n = 0; n < 4096; n++) {
863: if (spvSizeArray[n] < 0) {
864: spvSizeArray[n] = spvLastSizeArray[n];
865: }
866: }
867: for (int n = 0; n < 4 * 4096; n++) {
868: if (spvBlockArray[n] < 0) {
869: spvBlockArray[n] = spvLastBlockArray[n];
870: }
871: if (spvFlipArray[n] < 0) {
872: spvFlipArray[n] = spvLastFlipArray[n];
873: }
874: }
875: }
876:
877: int a = 32 * spvCellOffset;
878: for (int cRow = 0; cRow <= spvRowsMask; cRow++) {
879: int cY = spvRowToY (cRow);
880: for (int cCol = 0; cCol <= spvColsMask; cCol++) {
881: int cX = spvColToX (cCol);
882: int cIndex = cX + spvImageWidth * cY;
883:
884:
885: int i = cIndex;
886: for (int v = 0; v < SPV_CELL_HEIGHT; v++) {
887: for (int h = 0; h < SPV_CELL_WIDTH; h++) {
888: spvBitmap[i + h] = SPV_BACKGROUND_RGB;
889: }
890: i += spvImageWidth;
891: }
892: int n = (spvCellOffset + cCol + (cRow << spvColsBit)) << 2;
893: if (spvSizeArray[n >> 2] == 0) {
894: for (int qCol = 0; qCol < 2; qCol++) {
895: int qX = cX + SPV_CELL_WIDTH / 2 * qCol;
896: for (int qRow = 0; qRow < 2; qRow++) {
897: int qY = cY + SPV_CELL_HEIGHT / 2 * qRow;
898: int qIndex = qX + spvImageWidth * qY;
899: int pb = spvBlockArray[n];
900: int vh = spvFlipArray[n];
901: int hMask = (vh & 1) != 0 ? 7 : 0;
902: int vMask = (vh & 2) != 0 ? 15 : 0;
903:
904: i = qIndex + (hMask == 0 ? 0 + spvImageWidth * 1 :
905: 1 + 2 * 8 + spvImageWidth * 1);
906: for (int v = 0; v <= 15; v++) {
907: int vm = v ^ vMask;
908: if (vm == pb) {
909: spvBitmap[i] = SPV_BLOCK_DOT_RGB;
910: } else if (vm < 8) {
911: spvBitmap[i] = SPV_GRAY_LINE_RGB;
912: }
913: i += spvImageWidth * 1;
914: }
915:
916: pb <<= 4;
917: vMask >>= 1;
918: i = qIndex + 1 + spvImageWidth * 1;
919: for (int v = 0; v <= 7; v++) {
920: int vm = v ^ vMask;
921: int d = spvPat[a + vm];
922: for (int h = 7; 0 <= h; h--) {
923: int hm = h ^ hMask;
924: spvBitmap[i] =
925: spvBitmap[i + 1] =
926: spvBitmap[i + spvImageWidth] =
927: spvBitmap[i + spvImageWidth + 1] = spvPal32TS[pb + ((d >> (hm << 2)) & 15)];
928: i += 2;
929: }
930: i += spvImageWidth * 2 - 2 * 8;
931: }
932: a += 8;
933: n++;
934: }
935: }
936: } else {
937: int pb = spvBlockArray[n];
938: int vh = spvFlipArray[n];
939: int hMask = (vh & 1) != 0 ? 15 : 0;
940: int vMask = (vh & 2) != 0 ? 15 : 0;
941:
942: i = cIndex + (hMask == 0 ? 0 + spvImageWidth * 2 :
943: 2 + 2 * 16 + spvImageWidth * 2);
944: for (int v = 0; v <= 15; v++) {
945: int vm = v ^ vMask;
946: if (vm == pb) {
947: spvBitmap[i] =
948: spvBitmap[i + 1] =
949: spvBitmap[i + spvImageWidth] =
950: spvBitmap[i + spvImageWidth + 1] = SPV_BLOCK_DOT_RGB;
951: } else if (vm < 8) {
952: spvBitmap[i] =
953: spvBitmap[i + 1] =
954: spvBitmap[i + spvImageWidth] =
955: spvBitmap[i + spvImageWidth + 1] = SPV_GRAY_LINE_RGB;
956: }
957: i += spvImageWidth * 2;
958: }
959:
960: pb <<= 4;
961: i = cIndex + 2 + spvImageWidth * 2;
962: for (int v = 0; v <= 15; v++) {
963: int vm = v ^ vMask;
964: long d = ((long) spvPat[a + vm] << 32 |
965: (long) spvPat[a + vm + 16] & 0xffffffffL);
966: for (int h = 15; 0 <= h; h--) {
967: int hm = h ^ hMask;
968: spvBitmap[i] =
969: spvBitmap[i + 1] =
970: spvBitmap[i + spvImageWidth] =
971: spvBitmap[i + spvImageWidth + 1] = spvPal32TS[pb + ((int) (d >> (hm << 2)) & 15)];
972: i += 2;
973: }
974: i += spvImageWidth * 2 - 2 * 16;
975: }
976: a += 32;
977: }
978: }
979: }
980: spvCanvas.repaint ();
981: }
982:
983:
984:
985: static void spvSetStoppedOn () {
986: spvStopped = true;
987: spvStoppedRequest = true;
988:
989: System.arraycopy (SpriteScreen.sprNumPort, 0, spvCopiedNum, 0, SpriteScreen.SPR_COUNT);
990: System.arraycopy (SpriteScreen.sprColPort, 0, spvCopiedCol, 0, SpriteScreen.SPR_COUNT);
991: System.arraycopy (SpriteScreen.sprPrw, 0, spvCopiedPrw, 0, SpriteScreen.SPR_COUNT);
992: System.arraycopy (SpriteScreen.sprH, 0, spvCopiedH, 0, SpriteScreen.SPR_COUNT);
993: System.arraycopy (SpriteScreen.sprV, 0, spvCopiedV, 0, SpriteScreen.SPR_COUNT);
994: System.arraycopy (SpriteScreen.sprPatPort, 0, spvCopiedPat, 0, 32 * 4096);
995: System.arraycopy (SpriteScreen.sprTNum, 0, spvCopiedTNum, 0, 4096 * 4);
996: System.arraycopy (SpriteScreen.sprTColPort, 0, spvCopiedTCol, 0, 4096 * 4);
997: System.arraycopy (SpriteScreen.sprTH, 0, spvCopiedTH, 0, 4096 * 4);
998: System.arraycopy (SpriteScreen.sprTV, 0, spvCopiedTV, 0, 4096 * 4);
999: System.arraycopy (VideoController.vcnPalBase[VideoController.VCN_CONTRAST_SCALE * 15], 0, spvCopiedPalTbl, 0, 65536);
1000: System.arraycopy (VideoController.vcnPal16TSPort, 0, spvCopiedPal16TS, 0, 256);
1001:
1002: spvNum = spvCopiedNum;
1003: spvCol = spvCopiedCol;
1004: spvPrw = spvCopiedPrw;
1005: spvH = spvCopiedH;
1006: spvV = spvCopiedV;
1007: spvPat = spvCopiedPat;
1008: spvTNum = spvCopiedTNum;
1009: spvTCol = spvCopiedTCol;
1010: spvTH = spvCopiedTH;
1011: spvTV = spvCopiedTV;
1012: spvPalTbl = spvCopiedPalTbl;
1013: spvPal16TS = spvCopiedPal16TS;
1014: }
1015:
1016:
1017:
1018: static void spvSetStoppedOff () {
1019: spvStopped = false;
1020: spvStoppedRequest = false;
1021:
1022: spvNum = SpriteScreen.sprNumPort;
1023: spvCol = SpriteScreen.sprColPort;
1024: spvPrw = SpriteScreen.sprPrw;
1025: spvH = SpriteScreen.sprH;
1026: spvV = SpriteScreen.sprV;
1027: spvPat = SpriteScreen.sprPatPort;
1028: spvTNum = SpriteScreen.sprTNum;
1029: spvTCol = SpriteScreen.sprTColPort;
1030: spvTH = SpriteScreen.sprTH;
1031: spvTV = SpriteScreen.sprTV;
1032: spvPalTbl = VideoController.vcnPalBase[VideoController.VCN_CONTRAST_SCALE * 15];
1033: spvPal16TS = VideoController.vcnPal16TSPort;
1034: }
1035:
1036: }