SpritePatternViewer.java
     1: //========================================================================================
     2: //  SpritePatternViewer.java
     3: //    en:Sprite pattern viewer
     4: //    ja:スプライトパターンビュア
     5: //  Copyright (C) 2003-2024 Makoto Kamada
     6: //
     7: //  This file is part of the XEiJ (X68000 Emulator in Java).
     8: //  You can use, modify and redistribute the XEiJ if the conditions are met.
     9: //  Read the XEiJ License for more details.
    10: //  https://stdkmd.net/xeij/
    11: //========================================================================================
    12: 
    13: //----------------------------------------------------------------------------------------
    14: //!!! 工事中
    15: //  16x16のパターンを32x32に拡大して表示する
    16: //    パターン
    17: //      幅32px
    18: //      高さ32px
    19: //    セル
    20: //      幅32px+ギャップ4px=幅36px/列
    21: //      高さ32px+ギャップ8px=高さ40px/行
    22: //    パターンエリア
    23: //      幅36px/列*20列=幅720px
    24: //      高さ40px/行*13行=高さ520px
    25: //    PNL_STRETCH_BASEに従って水平方向に拡大してもよいがパネルの幅が変わってしまうので保留
    26: //  パレットブロックは自動的に選択する
    27: //    スプライトスクロールレジスタで使用されたことがあるとき
    28: //      最後に使用されたパレットブロック
    29: //    スプライトスクロールレジスタで使用されたことがないとき
    30: //      直前のパターンと同じパレットブロック
    31: //----------------------------------------------------------------------------------------
    32: 
    33: package xeij;
    34: 
    35: import java.awt.*;  //BasicStroke,BorderLayout,BoxLayout,Color,Component,Container,Cursor,Desktop,Dimension,Font,Frame,Graphics,Graphics2D,GraphicsDevice,GraphicsEnvironment,GridLayout,Image,Insets,Paint,Point,Rectangle,RenderingHints,Robot,Shape,Stroke,TexturePaint,Toolkit
    36: import java.awt.event.*;  //ActionEvent,ActionListener,ComponentAdapter,ComponentEvent,ComponentListener,FocusAdapter,FocusEvent,FocusListener,InputEvent,KeyAdapter,KeyEvent,KeyListener,MouseAdapter,MouseEvent,MouseListener,MouseMotionAdapter,MouseWheelEvent,WindowAdapter,WindowEvent,WindowListener,WindowStateListener
    37: import java.awt.image.*;  //BufferedImage,DataBuffer,DataBufferByte,DataBufferInt,IndexColorModel
    38: import java.lang.*;  //Boolean,Character,Class,Comparable,Double,Exception,Float,IllegalArgumentException,Integer,Long,Math,Number,Object,Runnable,SecurityException,String,StringBuilder,System
    39: import java.util.*;  //ArrayList,Arrays,Calendar,GregorianCalendar,HashMap,Map,Map.Entry,TimeZone,Timer,TimerTask,TreeMap
    40: import javax.swing.*;  //AbstractSpinnerModel,Box,ButtonGroup,DefaultListModel,ImageIcon,JApplet,JButton,JCheckBox,JCheckBoxMenuItem,JDialog,JFileChooser,JFrame,JLabel,JList,JMenu,JMenuBar,JMenuItem,JPanel,JRadioButton,JScrollPane,JSpinner,JTextArea,JTextField,JTextPane,JViewport,ScrollPaneConstants,SpinnerListModel,SpinnerNumberModel,SwingConstants,SwingUtilities,UIManager,UIDefaults,UnsupportedLookAndFeelException
    41: 
    42: public class SpritePatternViewer {
    43: 
    44:   public static final boolean SPV_ON = true;
    45: 
    46:   //キャンバス
    47:   public static final int SPV_CANVAS_WIDTH = 724;
    48:   public static final int SPV_CANVAS_HEIGHT = 522;
    49:   public static final int SPV_BACKGROUND_RGB = 0xff333333;  //背景色
    50:   public static final int SPV_NUMBER_HEX_RGB = 0xff999999;  //スプライト番号(16進数)の色
    51:   public static final int SPV_NUMBER_DEC_RGB = 0xffffffff;  //スプライト番号(10進数)の色
    52:   public static final int SPV_PALET_BLOCK_RGB = 0xff999999;  //パレットブロックの色
    53:   public static BufferedImage spvImage;  //イメージ
    54:   public static int[] spvBitmap;  //ビットマップ
    55: 
    56:   //パネル
    57:   public static JPanel spvPanel;  //パネル
    58: 
    59:   //ウインドウ
    60:   public static JFrame spvFrame;  //ウインドウ
    61: 
    62:   //タイマー
    63:   public static final int SPV_INTERVAL = 10;
    64:   public static int spvTimer;
    65: 
    66:   //パレットブロック
    67:   public static final int[] spvLastPaletBlock = new int[256];  //前回のパレットブロック<<4
    68:   public static final int[] spvPaletBlock = new int[256];  //パレットブロック<<4
    69: 
    70:   public static void spvInit () {
    71: 
    72:     //ウインドウ
    73:     spvFrame = null;
    74: 
    75:     //タイマー
    76:     spvTimer = 0;
    77: 
    78:     //パレットブロック
    79:     for (int n = 0; n < 256; n++) {
    80:       spvLastPaletBlock[n] = 0x10;
    81:     }
    82: 
    83:   }  //spvInit()
    84: 
    85:   //spvStart ()
    86:   public static void spvStart () {
    87:     if (RestorableFrame.rfmGetOpened (Settings.SGS_SPV_FRAME_KEY)) {
    88:       spvOpen ();
    89:     }
    90:   }  //spvStart()
    91: 
    92:   //spvOpen ()
    93:   //  スプライトパターンビュアを開く
    94:   public static void spvOpen () {
    95:     if (spvFrame == null) {
    96:       spvMakeFrame ();
    97:     } else {
    98:       spvUpdateFrame ();
    99:     }
   100:     XEiJ.dbgVisibleMask |= XEiJ.DBG_SPV_VISIBLE_MASK;
   101:     XEiJ.pnlExitFullScreen (false);
   102:     spvFrame.setVisible (true);
   103:   }  //spvOpen()
   104: 
   105:   //spvMakeFrame ()
   106:   //  スプライトパターンビュアを作る
   107:   //  ここでは開かない
   108:   public static void spvMakeFrame () {
   109: 
   110:     //キャンバス
   111:     spvImage = new BufferedImage (SPV_CANVAS_WIDTH, SPV_CANVAS_HEIGHT, BufferedImage.TYPE_INT_RGB);
   112:     spvBitmap = ((DataBufferInt) spvImage.getRaster ().getDataBuffer ()).getData ();
   113:     Arrays.fill (spvBitmap, SPV_BACKGROUND_RGB);
   114:     for (int n = 0; n < 256; n++) {
   115:       //  perl misc/optdiv.pl 255 20
   116:       //  x/20==x*205>>>12 (0<=x<=1038) [255*205==52275]
   117:       int ny = n * 205 >>> 12;
   118:       int nx = n - 20 * ny;
   119:       int x0 = 4 + 36 * nx;
   120:       int y0 = 8 + 40 * ny;
   121:       int i0 = x0 + SPV_CANVAS_WIDTH * y0;
   122:       //0x10の位
   123:       {
   124:         int t = n >>> 4;
   125:         spvPutc (-6 * SPV_CANVAS_WIDTH + i0, (9 - t >> 4 & 7 | 48) + t, SPV_NUMBER_HEX_RGB);
   126:       }
   127:       //0x1の位
   128:       {
   129:         int t = n & 15;
   130:         spvPutc (4 + -6 * SPV_CANVAS_WIDTH + i0, (9 - t >> 4 & 7 | 48) + t, SPV_NUMBER_HEX_RGB);
   131:       }
   132:       //100の位
   133:       int bcd = XEiJ.FMT_BCD4[n];
   134:       if (100 <= n) {
   135:         spvPutc (10 + -6 * SPV_CANVAS_WIDTH + i0, bcd >>> 8 | 48, SPV_NUMBER_DEC_RGB);
   136:       }
   137:       //10の位
   138:       if (10 <= n) {
   139:         spvPutc (14 + -6 * SPV_CANVAS_WIDTH + i0, bcd >>> 4 & 15 | 48, SPV_NUMBER_DEC_RGB);
   140:       }
   141:       //1の位
   142:       spvPutc (18 + -6 * SPV_CANVAS_WIDTH + i0, bcd & 15 | 48, SPV_NUMBER_DEC_RGB);
   143:     }  //for n
   144: 
   145:     //パネル
   146:     spvPanel = ComponentFactory.setFixedSize (
   147:       new JPanel () {
   148:         @Override protected void paintComponent (Graphics g) {
   149:           g.drawImage (spvImage, 0, 0, null);
   150:         }
   151:         @Override protected void paintBorder (Graphics g) {
   152:         }
   153:         @Override protected void paintChildren (Graphics g) {
   154:         }
   155:       },
   156:       SPV_CANVAS_WIDTH, SPV_CANVAS_HEIGHT);
   157:     spvPanel.setBackground (Color.black);
   158:     spvPanel.setOpaque (true);
   159: 
   160:     //ウインドウ
   161:     spvFrame = Multilingual.mlnTitle (
   162:       ComponentFactory.createRestorableSubFrame (
   163:         Settings.SGS_SPV_FRAME_KEY,
   164:         "Sprite Pattern Viewer",
   165:         null,
   166:         spvPanel
   167:         ),
   168:       "ja", "スプライトパターンビュア");  //Multilingual.mlnTitle
   169: 
   170:     //  ウインドウリスナー
   171:     ComponentFactory.addListener (
   172:       spvFrame,
   173:       new WindowAdapter () {
   174:         @Override public void windowClosing (WindowEvent we) {
   175:           XEiJ.dbgVisibleMask &= ~XEiJ.DBG_SPV_VISIBLE_MASK;
   176:         }
   177:       });
   178: 
   179:   }  //spvMakeFrame()
   180: 
   181:   //spvUpdateFrame ()
   182:   //  スプライトパターンビュアを更新する
   183:   public static void spvUpdateFrame () {
   184: 
   185:     if (spvFrame == null) {
   186:       return;
   187:     }
   188: 
   189:     //パレットブロック
   190:     for (int n = 0; n < 256; n++) {
   191:       spvPaletBlock[n] = -1;
   192:     }
   193:     for (int sn = 0; sn < 128; sn++) {  //スプライト番号
   194:       int n = SpriteScreen.sprNum[sn];  //パターン番号
   195:       if (spvPaletBlock[n] < 0) {
   196:         spvPaletBlock[n] = spvLastPaletBlock[n] = SpriteScreen.sprColPort[sn];  //パレットブロック<<4
   197:       }
   198:     }
   199:     for (int n = 0; n < 256; n++) {
   200:       if (spvPaletBlock[n] < 0) {
   201:         spvPaletBlock[n] = spvLastPaletBlock[n];
   202:       }
   203:     }
   204:     int a = 0;
   205:     for (int n = 0; n < 256; n++) {
   206:       //  perl misc/optdiv.pl 255 20
   207:       //  x/20==x*205>>>12 (0<=x<=1038) [255*205==52275]
   208:       int ny = n * 205 >>> 12;
   209:       int nx = n - 20 * ny;
   210:       int x0 = 4 + 36 * nx;
   211:       int y0 = 8 + 40 * ny;
   212:       int i0 = x0 + SPV_CANVAS_WIDTH * y0;
   213:       //パレットブロック
   214:       int p = spvPaletBlock[n];  //パレットブロック<<4
   215:       //10の位
   216:       spvPutc (24 + -6 * SPV_CANVAS_WIDTH + i0, p < 0xa0 ? ' ' : '1', SPV_PALET_BLOCK_RGB);
   217:       //1の位
   218:       spvPutc (28 + -6 * SPV_CANVAS_WIDTH + i0, (p < 0xa0 ? p : p - 0xa0) >>> 4 | 48, SPV_PALET_BLOCK_RGB);
   219:       //パターン
   220:       //  +---+---+
   221:       //  | 0 | 2 |
   222:       //  +---+---+
   223:       //  | 1 | 3 |
   224:       //  +---+---+
   225:       for (int u = 0; u < 32; u += 16) {
   226:         for (int v = 0; v < 32; v += 2) {
   227:           int d = SpriteScreen.sprPatPort[a++];
   228:           int i = u + v * SPV_CANVAS_WIDTH + i0;
   229:           int t = VideoController.vcnPal32TS[d >>> 28 | p];
   230:           spvBitmap[                        i] = t;
   231:           spvBitmap[ 1 +                    i] = t;
   232:           spvBitmap[     SPV_CANVAS_WIDTH + i] = t;
   233:           spvBitmap[ 1 + SPV_CANVAS_WIDTH + i] = t;
   234:           t = VideoController.vcnPal32TS[d >>> 24 & 15 | p];
   235:           spvBitmap[ 2 +                    i] = t;
   236:           spvBitmap[ 3 +                    i] = t;
   237:           spvBitmap[ 2 + SPV_CANVAS_WIDTH + i] = t;
   238:           spvBitmap[ 3 + SPV_CANVAS_WIDTH + i] = t;
   239:           t = VideoController.vcnPal32TS[d >>> 20 & 15 | p];
   240:           spvBitmap[ 4 +                    i] = t;
   241:           spvBitmap[ 5 +                    i] = t;
   242:           spvBitmap[ 4 + SPV_CANVAS_WIDTH + i] = t;
   243:           spvBitmap[ 5 + SPV_CANVAS_WIDTH + i] = t;
   244:           t = VideoController.vcnPal32TS[d >>> 16 & 15 | p];
   245:           spvBitmap[ 6 +                    i] = t;
   246:           spvBitmap[ 7 +                    i] = t;
   247:           spvBitmap[ 6 + SPV_CANVAS_WIDTH + i] = t;
   248:           spvBitmap[ 7 + SPV_CANVAS_WIDTH + i] = t;
   249:           t = VideoController.vcnPal32TS[(char) d >>> 12 | p];
   250:           spvBitmap[ 8 +                    i] = t;
   251:           spvBitmap[ 9 +                    i] = t;
   252:           spvBitmap[ 8 + SPV_CANVAS_WIDTH + i] = t;
   253:           spvBitmap[ 9 + SPV_CANVAS_WIDTH + i] = t;
   254:           t = VideoController.vcnPal32TS[d >>> 8 & 15 | p];
   255:           spvBitmap[10 +                    i] = t;
   256:           spvBitmap[11 +                    i] = t;
   257:           spvBitmap[10 + SPV_CANVAS_WIDTH + i] = t;
   258:           spvBitmap[11 + SPV_CANVAS_WIDTH + i] = t;
   259:           t = VideoController.vcnPal32TS[d >>> 4 & 15 | p];
   260:           spvBitmap[12 +                    i] = t;
   261:           spvBitmap[13 +                    i] = t;
   262:           spvBitmap[12 + SPV_CANVAS_WIDTH + i] = t;
   263:           spvBitmap[13 + SPV_CANVAS_WIDTH + i] = t;
   264:           t = VideoController.vcnPal32TS[d & 15 | p];
   265:           spvBitmap[14 +                    i] = t;
   266:           spvBitmap[15 +                    i] = t;
   267:           spvBitmap[14 + SPV_CANVAS_WIDTH + i] = t;
   268:           spvBitmap[15 + SPV_CANVAS_WIDTH + i] = t;
   269:         }  //for v
   270:       }  //for u
   271:     }  //for n
   272:     spvPanel.repaint ();
   273: 
   274:   }  //spvUpdateFrame()
   275: 
   276:   public static void spvPutc (int i, int c, int f) {
   277:     int t = Indicator.IND_ASCII_3X5[c];
   278:     spvBitmap[                           i] = t << 31 - 14 < 0 ? f : SPV_BACKGROUND_RGB;
   279:     spvBitmap[1 +                        i] = t << 31 - 13 < 0 ? f : SPV_BACKGROUND_RGB;
   280:     spvBitmap[2 +                        i] = t << 31 - 12 < 0 ? f : SPV_BACKGROUND_RGB;
   281:     spvBitmap[    1 * SPV_CANVAS_WIDTH + i] = t << 31 - 11 < 0 ? f : SPV_BACKGROUND_RGB;
   282:     spvBitmap[1 + 1 * SPV_CANVAS_WIDTH + i] = t << 31 - 10 < 0 ? f : SPV_BACKGROUND_RGB;
   283:     spvBitmap[2 + 1 * SPV_CANVAS_WIDTH + i] = t << 31 -  9 < 0 ? f : SPV_BACKGROUND_RGB;
   284:     spvBitmap[    2 * SPV_CANVAS_WIDTH + i] = t << 31 -  8 < 0 ? f : SPV_BACKGROUND_RGB;
   285:     spvBitmap[1 + 2 * SPV_CANVAS_WIDTH + i] = t << 31 -  7 < 0 ? f : SPV_BACKGROUND_RGB;
   286:     spvBitmap[2 + 2 * SPV_CANVAS_WIDTH + i] = t << 31 -  6 < 0 ? f : SPV_BACKGROUND_RGB;
   287:     spvBitmap[    3 * SPV_CANVAS_WIDTH + i] = t << 31 -  5 < 0 ? f : SPV_BACKGROUND_RGB;
   288:     spvBitmap[1 + 3 * SPV_CANVAS_WIDTH + i] = t << 31 -  4 < 0 ? f : SPV_BACKGROUND_RGB;
   289:     spvBitmap[2 + 3 * SPV_CANVAS_WIDTH + i] = t << 31 -  3 < 0 ? f : SPV_BACKGROUND_RGB;
   290:     spvBitmap[    4 * SPV_CANVAS_WIDTH + i] = t << 31 -  2 < 0 ? f : SPV_BACKGROUND_RGB;
   291:     spvBitmap[1 + 4 * SPV_CANVAS_WIDTH + i] = t << 31 -  1 < 0 ? f : SPV_BACKGROUND_RGB;
   292:     spvBitmap[2 + 4 * SPV_CANVAS_WIDTH + i] = t << 31 -  0 < 0 ? f : SPV_BACKGROUND_RGB;
   293:   }  //spvPutc(int,int)
   294: 
   295: }  //class SpritePatternViewer
   296: 
   297: 
   298: