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.lang.*;
21: import java.util.*;
22: import javax.swing.*;
23: import javax.swing.event.*;
24:
25: public class SpritePatternViewer {
26:
27: public static final boolean SPV_ON = true;
28:
29:
30: static final int SPV_COLS = 16;
31: static final int SPV_ROWS = 16;
32: static final int SPV_LEFT_MARGIN = 20;
33: static final int SPV_TOP_MARGIN = 20;
34: static final int SPV_SPACE = 4;
35: static final int SPV_WIDTH = SPV_LEFT_MARGIN + (32 + SPV_SPACE) * SPV_COLS;
36: static final int SPV_HEIGHT = SPV_TOP_MARGIN + (32 + SPV_SPACE) * SPV_ROWS;
37: static final int SPV_BACKGROUND_RGB = 0xff333333;
38: static final int SPV_FOREGROUND_RGB = 0xffffffff;
39: static final String SPV_FONT_NAME = "Dialog";
40: static final int SPV_FONT_STYLE = Font.PLAIN;
41: static final int SPV_FONT_SIZE = 12;
42:
43:
44: static BufferedImage spvImage;
45:
46:
47: static int[] spvBitmap;
48:
49:
50: static JPanel spvCanvas;
51: static JScrollPane spvScrollPane;
52:
53:
54: static int spvBankNumber;
55: static JSpinner spvBankSpinner;
56: static SpinnerNumberModel spvBankModel;
57:
58:
59:
60: static final int[] spvLastBlockArray = new int[4 * 4096];
61: static final int[] spvBlockArray = new int[4 * 4096];
62: static boolean spvAutoBlock;
63: static int spvFixedBlock;
64: static JSpinner spvBlockSpinner;
65: static SpinnerNumberModel spvBlockModel;
66:
67:
68: static boolean spvStopped;
69:
70:
71: static JFrame spvFrame;
72:
73:
74: public static final int SPV_INTERVAL = 10;
75: public static int spvTimer;
76:
77:
78:
79: public static void spvInit () {
80:
81:
82: spvBankNumber = 0;
83:
84:
85: for (int n = 0; n < 4 * 4096; n++) {
86: spvLastBlockArray[n] = 1 << 4;
87: }
88: spvAutoBlock = true;
89: spvFixedBlock = 1;
90:
91:
92: spvStopped = false;
93:
94:
95: spvFrame = null;
96:
97:
98: spvTimer = 0;
99:
100: }
101:
102:
103:
104: public static void spvStart () {
105: if (RestorableFrame.rfmGetOpened (Settings.SGS_SPV_FRAME_KEY)) {
106: spvOpen ();
107: }
108: }
109:
110:
111:
112: public static void spvOpen () {
113: if (spvFrame == null) {
114: spvMakeFrame ();
115: } else {
116: spvUpdateFrame ();
117: }
118: XEiJ.dbgVisibleMask |= XEiJ.DBG_SPV_VISIBLE_MASK;
119: XEiJ.pnlExitFullScreen (false);
120: spvFrame.setVisible (true);
121: }
122:
123:
124:
125:
126: static void spvMakeFrame () {
127:
128:
129: spvImage = new BufferedImage (SPV_WIDTH, SPV_HEIGHT, BufferedImage.TYPE_INT_ARGB);
130: Graphics2D g2 = spvImage.createGraphics ();
131: g2.setColor (new Color (SPV_BACKGROUND_RGB));
132: g2.fillRect (0, 0, SPV_WIDTH, SPV_HEIGHT);
133: g2.setColor (new Color (SPV_FOREGROUND_RGB));
134: Font font = new Font (SPV_FONT_NAME, SPV_FONT_STYLE, SPV_FONT_SIZE);
135: g2.setFont (font);
136: FontRenderContext frc = g2.getFontRenderContext ();
137: for (int i = 0; i < 16; i++) {
138: String s = String.format ("x%X", i);
139: TextLayout tl = new TextLayout (s, font, frc);
140: Rectangle2D r = tl.getBounds ();
141: int rx = (int) Math.round (r.getX ());
142: int ry = (int) Math.round (r.getY ());
143: int rw = (int) Math.round (r.getWidth ());
144: int rh = (int) Math.round (r.getHeight ());
145: int bx = SPV_LEFT_MARGIN + (32 + SPV_SPACE) * i + 32 / 2;
146: int by = SPV_TOP_MARGIN - SPV_SPACE;
147: g2.drawString (s, bx - rx - rw / 2, by - ry - rh);
148: }
149: for (int i = 0; i < 16; i++) {
150: String s = String.format ("%Xx", i);
151: TextLayout tl = new TextLayout (s, font, frc);
152: Rectangle2D r = tl.getBounds ();
153: int rx = (int) Math.round (r.getX ());
154: int ry = (int) Math.round (r.getY ());
155: int rw = (int) Math.round (r.getWidth ());
156: int rh = (int) Math.round (r.getHeight ());
157: int bx = SPV_LEFT_MARGIN - SPV_SPACE;
158: int by = SPV_TOP_MARGIN + (32 + SPV_SPACE) * i + 32 / 2;
159: g2.drawString (s, bx - rx - rw, by - ry - rh / 2);
160: }
161:
162:
163: spvBitmap = ((DataBufferInt) spvImage.getRaster ().getDataBuffer ()).getData ();
164:
165:
166: spvCanvas = ComponentFactory.setFixedSize (
167: new JPanel () {
168: @Override protected void paintComponent (Graphics g) {
169: super.paintComponent (g);
170: g.drawImage (spvImage, 0, 0, null);
171: }
172: @Override protected void paintBorder (Graphics g) {
173: }
174: @Override protected void paintChildren (Graphics g) {
175: }
176: },
177: SPV_WIDTH, SPV_HEIGHT);
178: spvCanvas.setBackground (new Color (SPV_BACKGROUND_RGB));
179: spvCanvas.setOpaque (true);
180: spvScrollPane = ComponentFactory.setPreferredSize (
181: new JScrollPane (spvCanvas),
182: SPV_WIDTH + 20, SPV_HEIGHT + 20);
183:
184:
185: ActionListener listener = new ActionListener () {
186: @Override public void actionPerformed (ActionEvent ae) {
187: Object source = ae.getSource ();
188: String command = ae.getActionCommand ();
189: switch (command) {
190: case "Stop":
191: spvStopped = ((JCheckBox) source).isSelected ();
192: break;
193: case "Auto ":
194: spvAutoBlock = true;
195: break;
196: case "Fixed ":
197: spvAutoBlock = false;
198: break;
199: default:
200: System.out.println ("unknown action command " + command);
201: }
202: }
203: };
204:
205:
206: ButtonGroup paletGroup = new ButtonGroup ();
207: spvFrame = Multilingual.mlnTitle (
208: ComponentFactory.createRestorableSubFrame (
209: Settings.SGS_SPV_FRAME_KEY,
210: "Sprite Pattern Viewer",
211: null,
212: ComponentFactory.createBorderPanel (
213: 0, 0,
214:
215: spvScrollPane,
216:
217: ComponentFactory.createHorizontalBox (
218: Box.createHorizontalGlue (),
219: Multilingual.mlnText (
220: ComponentFactory.createLabel ("Bank "),
221: "ja", "バンク "),
222: spvBankSpinner = ComponentFactory.createNumberSpinner (
223: spvBankModel = new SpinnerNumberModel (spvBankNumber, 0, 15, 1),
224: 2,
225: new ChangeListener () {
226: @Override public void stateChanged (ChangeEvent ce) {
227: spvBankNumber = spvBankModel.getNumber ().intValue ();
228: }
229: }
230: ),
231: Box.createHorizontalStrut (20),
232: Multilingual.mlnText (
233: ComponentFactory.createLabel ("Palet "),
234: "ja", "パレット "),
235: Multilingual.mlnText (
236: ComponentFactory.createRadioButton (paletGroup, spvAutoBlock, "Auto ", listener),
237: "ja", "自動 "),
238: Multilingual.mlnText (
239: ComponentFactory.createRadioButton (paletGroup, !spvAutoBlock, "Fixed ", listener),
240: "ja", "固定 "),
241: spvBlockSpinner = ComponentFactory.createNumberSpinner (
242: spvBlockModel = new SpinnerNumberModel (spvFixedBlock, 0, 15, 1),
243: 2,
244: new ChangeListener () {
245: @Override public void stateChanged (ChangeEvent ce) {
246: spvFixedBlock = spvBlockModel.getNumber ().intValue ();
247: }
248: }
249: ),
250: Box.createHorizontalStrut (20),
251: Multilingual.mlnText (
252: ComponentFactory.createCheckBox (spvStopped, "Stop", listener),
253: "ja", "停止"),
254: Box.createHorizontalGlue ()
255: )
256: )
257: ),
258: "ja", "スプライトパターンビュア");
259:
260:
261: ComponentFactory.addListener (
262: spvFrame,
263: new WindowAdapter () {
264: @Override public void windowClosing (WindowEvent we) {
265: XEiJ.dbgVisibleMask &= ~XEiJ.DBG_SPV_VISIBLE_MASK;
266: }
267: });
268:
269: }
270:
271:
272:
273: static void spvUpdateFrame () {
274: if (spvFrame == null) {
275: return;
276: }
277: if (spvStopped) {
278: return;
279: }
280:
281: if (spvAutoBlock) {
282:
283:
284: Arrays.fill (spvBlockArray, -1);
285:
286: for (int sn = 0; sn < SpriteScreen.sprNumberOfSprites; sn++) {
287: if (256 <= sn && sn < 256 + 8) {
288: continue;
289: }
290: if (SpriteScreen.sprPrw[sn] != 0) {
291: int n = 4 * SpriteScreen.sprNumPort[sn];
292: int p = SpriteScreen.sprColPort[sn];
293: for (int cr = 0; cr < 4; cr++) {
294: if (spvBlockArray[n] < 0) {
295: spvBlockArray[n] =
296: spvLastBlockArray[n] = p;
297: }
298: n++;
299: }
300: }
301: }
302:
303: int tm = 0;
304: if ((SpriteScreen.sprReg4BgCtrlPort & 1) != 0) {
305: tm |= 1 << ((SpriteScreen.sprReg4BgCtrlPort >> 1) & 3);
306: }
307: if (((SpriteScreen.sprReg8ResoPort & 3) == 0 ||
308: SpriteScreen.spr512bg1) &&
309: (SpriteScreen.sprReg4BgCtrlPort & 8) != 0) {
310: tm |= 1 << ((SpriteScreen.sprReg4BgCtrlPort >> 4) & 3);
311: }
312: if ((SpriteScreen.sprReg8ResoPort & 3) == 0) {
313: for (int tp = 0; tp < 4; tp++) {
314: if ((tm & (1 << tp)) != 0) {
315: int o = 4096 * tp;
316: for (int i = 0; i < 4096; i++) {
317: int n = SpriteScreen.sprTNum[o + i] >> 3;
318: int p = SpriteScreen.sprTColPort[o + i];
319: if (spvBlockArray[n] < 0) {
320: spvBlockArray[n] =
321: spvLastBlockArray[n] = p;
322: }
323: }
324: }
325: }
326: } else {
327: for (int tp = 0; tp < 4; tp++) {
328: if ((tm & (1 << tp)) != 0) {
329: int o = 4096 * tp;
330: for (int i = 0; i < 4096; i++) {
331: int n = SpriteScreen.sprTNum[o + i] >> 1;
332: int p = SpriteScreen.sprTColPort[o + i];
333: for (int cr = 0; cr < 4; cr++) {
334: if (spvBlockArray[n] < 0) {
335: spvBlockArray[n] =
336: spvLastBlockArray[n] = p;
337: }
338: n++;
339: }
340: }
341: }
342: }
343: }
344:
345: for (int n = 0; n < 4 * 4096; n++) {
346: if (spvBlockArray[n] < 0) {
347: spvBlockArray[n] = spvLastBlockArray[n];
348: }
349: }
350: } else {
351: Arrays.fill (spvBlockArray, spvFixedBlock << 4);
352: }
353:
354:
355: int a = 32 * SPV_COLS * SPV_ROWS * spvBankNumber;
356: for (int rr = 0; rr < SPV_ROWS; rr++) {
357: int yy = SPV_TOP_MARGIN + (32 + SPV_SPACE) * rr;
358: for (int cc = 0; cc < SPV_COLS; cc++) {
359: int xx = SPV_LEFT_MARGIN + (32 + SPV_SPACE) * cc;
360: int ii = xx + SPV_WIDTH * yy;
361: int jj = ii - 2;
362: for (int vv = 0; vv < 16; vv++) {
363: spvBitmap[jj] =
364: spvBitmap[jj + 1] =
365: spvBitmap[jj + SPV_WIDTH] =
366: spvBitmap[jj + SPV_WIDTH + 1] = SPV_BACKGROUND_RGB;
367: jj += SPV_WIDTH * 2;
368: }
369: int n = 4 * (SPV_COLS * SPV_ROWS * spvBankNumber + cc + SPV_COLS * rr);
370: for (int c = 0; c < 2; c++) {
371: int x = xx + 16 * c;
372: for (int r = 0; r < 2; r++) {
373: int y = yy + 16 * r;
374: int i = x + SPV_WIDTH * y;
375: int p = spvBlockArray[n];
376: int j = ii - 2 + SPV_WIDTH * 2 * (p >> 4);
377: spvBitmap[j] =
378: spvBitmap[j + 1] =
379: spvBitmap[j + SPV_WIDTH] =
380: spvBitmap[j + SPV_WIDTH + 1] = SPV_FOREGROUND_RGB;
381: for (int v = 0; v < 8; v++) {
382: int d = SpriteScreen.sprPatPort[a++];
383: for (int u = 0; u < 8; u++) {
384: spvBitmap[i] =
385: spvBitmap[i + 1] =
386: spvBitmap[i + SPV_WIDTH] =
387: spvBitmap[i + SPV_WIDTH + 1] = VideoController.vcnPal32TS[p + ((d >> ((~u & 7) << 2)) & 15)];
388: i += 2;
389: }
390: i += 2 * SPV_WIDTH - 2 * 8;
391: }
392: n++;
393: }
394: }
395: }
396: }
397: spvCanvas.repaint ();
398:
399: }
400:
401: }
402:
403:
404: