SpriteScreen.java
     1: //========================================================================================
     2: //  SpriteScreen.java
     3: //    en:Sprite screen
     4: //    ja:スプライト画面
     5: //  Copyright (C) 2003-2017 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: //  http://stdkmd.com/xeij/
    11: //========================================================================================
    12: 
    13: package xeij;
    14: 
    15: import java.lang.*;  //Boolean,Character,Class,Comparable,Double,Exception,Float,IllegalArgumentException,Integer,Long,Math,Number,Object,Runnable,SecurityException,String,StringBuilder,System
    16: import java.util.*;  //ArrayList,Arrays,Calendar,GregorianCalendar,HashMap,Map,Map.Entry,Timer,TimerTask,TreeMap
    17: 
    18: public class SpriteScreen {
    19: 
    20:   //スイッチ
    21:   public static final int SPR_HORIZONTAL_LIMIT = 0;  //スプライトの水平表示限界。0=無制限,32=標準
    22: 
    23:   //レジスタ
    24:   public static final int SPR_REG0_BG0_X   = 0x00eb0800;  //9-0 BG0スクロールX座標
    25:   public static final int SPR_REG1_BG0_Y   = 0x00eb0802;  //9-0 BG0スクロールY座標
    26:   public static final int SPR_REG2_BG1_X   = 0x00eb0804;  //9-0 BG1スクロールX座標
    27:   public static final int SPR_REG3_BG1_Y   = 0x00eb0806;  //9-0 BG1スクロールY座標
    28:   public static final int SPR_REG4_BG_CTRL = 0x00eb0808;  //9   0=スプライト画面表示OFF,1=スプライト画面表示ON
    29:   //                                                        5-4 BG1 00=BG1にTEXT0を割り当てる,01=BG1にTEXT1を割り当てる
    30:   //                                                        3   BG1 0=BG1表示OFF,1=BG1表示ON
    31:   //                                                        2-1 BG0 00=BG0にTEXT0を割り当てる,01=BG0にTEXT1を割り当てる
    32:   //                                                        0   BG0 0=BG0表示OFF,1=BG0表示ON
    33:   public static final int SPR_REG5_H_TOTAL = 0x00eb080a;  //7-0 スプライト画面水平表示終了位置(水平トータル)
    34:   public static final int SPR_REG6_H_START = 0x00eb080c;  //5-0 スプライト画面水平映像開始位置
    35:   public static final int SPR_REG7_V_START = 0x00eb080e;  //7-0 スプライト画面垂直映像開始位置
    36:   public static final int SPR_REG8_RESO    = 0x00eb0810;  //4   スプライト画面解像度 0=低解像度,1=高解像度
    37:   //                                                        3-2 スプライト画面垂直サイズ 00=256,01=512
    38:   //                                                        1-0 スプライト画面水平サイズ
    39:   //                                                            00=256(BGパターンは8x8,BG仮想画面は512x512)
    40:   //                                                            01=512(BGパターンは16x16,BG仮想画面は1024x1024,BG0のみ)
    41: 
    42:   //レジスタ
    43:   //  ゼロ拡張
    44:   public static int sprReg0Bg0XPort;
    45:   public static int sprReg0Bg0XMask;
    46:   public static int sprReg0Bg0XTest;
    47:   public static int sprReg0Bg0XCurr;
    48:   public static int sprReg1Bg0YPort;
    49:   public static int sprReg1Bg0YMask;
    50:   public static int sprReg1Bg0YTest;
    51:   public static int sprReg1Bg0YCurr;
    52:   public static int sprReg2Bg1XPort;
    53:   public static int sprReg2Bg1XMask;
    54:   public static int sprReg2Bg1XTest;
    55:   public static int sprReg2Bg1XCurr;
    56:   public static int sprReg3Bg1YPort;
    57:   public static int sprReg3Bg1YMask;
    58:   public static int sprReg3Bg1YTest;
    59:   public static int sprReg3Bg1YCurr;
    60:   public static int sprReg4BgCtrlPort;  //ポートの読み書きに使われる値
    61:   public static int sprReg4BgCtrlMask;  //マスク。0=ポート,1=テスト
    62:   public static int sprReg4BgCtrlTest;  //テストデータ
    63:   public static int sprReg4BgCtrlCurr;  //使用されている値。sprReg4BgCtrlPort & ~sprReg4BgCtrlMask | sprReg4BgCtrlTest & sprReg4BgCtrlMask
    64:   public static int sprReg5HTotalPort;
    65:   public static int sprReg5HTotalMask;
    66:   public static int sprReg5HTotalTest;
    67:   public static int sprReg5HTotalCurr;
    68:   public static int sprReg6HStartPort;
    69:   public static int sprReg6HStartMask;
    70:   public static int sprReg6HStartTest;
    71:   public static int sprReg6HStartCurr;
    72:   public static int sprReg7VStartPort;
    73:   public static int sprReg7VStartMask;
    74:   public static int sprReg7VStartTest;
    75:   public static int sprReg7VStartCurr;
    76:   public static int sprReg8ResoPort;  //ポートの読み書きに使われる値
    77:   public static int sprReg8ResoMask;  //マスク。0=ポート,1=テスト
    78:   public static int sprReg8ResoTest;  //テストデータ
    79:   public static int sprReg8ResoCurr;  //使用されている値。sprReg8ResoPort & ~sprReg8ResoMask | sprReg8ResoTest & sprReg8ResoMask
    80: 
    81:   //スプライトスクロールレジスタ
    82:   public static final short[] sprX = new short[128];  //x座標(0~1023)
    83:   public static final short[] sprY = new short[128];  //y座標(0~1023)
    84:   public static final short[] sprNum = new short[128];  //パターン番号(0~255)
    85:   public static final short[] sprColPort = new short[128];  //パレットブロック(0~15)<<4
    86:   public static final byte[] sprPrw = new byte[128];  //プライオリティ(0~3)
    87:   public static final boolean[] sprH = new boolean[128];  //水平反転
    88:   public static final boolean[] sprV = new boolean[128];  //垂直反転
    89: 
    90:   //ラスタ毎にどのスプライトが含まれているかを示すテーブル
    91:   //  1ラスタあたりint*4=128ビット
    92:   //  プライオリティが0のスプライトは含まれない
    93:   //  スプライト座標は1023までで縦16ビットなので1038まで1039ラスタ必要
    94:   //  下からはみ出したスプライトが上から出てくるということはない
    95:   //  [16]が画面上の最初のラスタになるので描画の際に注意すること
    96:   public static final int[] sprRmap0 = new int[1039];
    97:   public static final int[] sprRmap1 = new int[1039];
    98:   public static final int[] sprRmap2 = new int[1039];
    99:   public static final int[] sprRmap3 = new int[1039];
   100:   public static final int[][] sprRmap = { sprRmap0, sprRmap1, sprRmap2, sprRmap3 };
   101:   public static final boolean SPR_RRMAP = true;
   102:   public static final int[] sprRRmap = new int[1039 << 2];
   103: 
   104:   //パターン
   105:   //  1要素に8ピクセル(4*8=32ビット)ずつ入れる
   106:   //  上位が左側のピクセル
   107:   public static final int[] sprPatPort = new int[8192];
   108: 
   109:   //パターン毎にどのスプライトが使用されているかを示すテーブル
   110:   //  1パターンあたりint*4=128ビット
   111:   //  プライオリティが0のスプライトは含まれない
   112:   public static final int[] sprPmap0 = new int[256];
   113:   public static final int[] sprPmap1 = new int[256];
   114:   public static final int[] sprPmap2 = new int[256];
   115:   public static final int[] sprPmap3 = new int[256];
   116:   public static final int[][] sprPmap = { sprPmap0, sprPmap1, sprPmap2, sprPmap3 };
   117:   public static final int[] sprPPmap = new int[256 << 2];
   118: 
   119:   //テキストエリア
   120:   public static final short[] sprT0Num = new short[4096];  //テキストエリア0 パターン番号<<3
   121:   public static final short[] sprT0ColPort = new short[4096];  //テキストエリア0 パレットブロック<<4
   122:   public static short[] sprT0ColCurr;
   123:   public static final boolean[] sprT0H = new boolean[4096];  //テキストエリア0 水平反転
   124:   public static final boolean[] sprT0V = new boolean[4096];  //テキストエリア0 垂直反転。0=しない,15=する
   125:   public static final short[] sprT1Num = new short[4096];  //テキストエリア1 パターン番号<<3
   126:   public static final short[] sprT1ColPort = new short[4096];  //テキストエリア1 パレットブロック<<4
   127:   public static short[] sprT1ColCurr;
   128:   public static final boolean[] sprT1H = new boolean[4096];  //テキストエリア1 水平反転
   129:   public static final boolean[] sprT1V = new boolean[4096];  //テキストエリア1 垂直反転。0=しない,15=する
   130: 
   131:   public static final boolean SPR_THREE_STEPS = true;
   132:   public static int[] sprBuffer;  //表バッファ
   133:   public static int[] sprShadowBuffer;  //裏バッファ
   134:   public static boolean sprActive;  //垂直映像期間の先頭で(sprReg8ResoCurr&10)==0のとき、そのフレームはスプライト画面が構築され、すべてのラスタが描画される
   135: 
   136:   //パターンテスト
   137:   public static final boolean SPR_PATTEST_ON = true;
   138:   public static final int SPR_PATTEST_MARK = '˙';  //上下左右の反転を示す印。'^'(U+005E;CIRCUMFLEX ACCENT),'~'(U+007E;TILDE),'¨'(U+00A8;DIAERESIS),'˙'(U+02D9;DOT ABOVE)
   139:   public static final int[] sprPatTest = new int[8192];
   140:   public static int[] sprPatCurr;
   141:   public static final short[] sprColTest = new short[128];  //パターンテスト用のパレットブロック(Sp)。(16~19)<<4
   142:   public static final short[] sprT0ColTest = new short[4096];  //パターンテスト用のパレットブロック(T0)。20<<4
   143:   public static final short[] sprT1ColTest = new short[4096];  //パターンテスト用のパレットブロック(T1)。21<<4
   144:   public static short[] sprColCurr;  //現在のパレットブロック(0~16)<<4
   145: 
   146:   //sprInit ()
   147:   //  スプライト画面を初期化する
   148:   public static void sprInit () {
   149:     sprReg0Bg0XPort = 0;
   150:     sprReg0Bg0XMask = 0;
   151:     sprReg0Bg0XTest = 0;
   152:     sprReg0Bg0XCurr = 0;
   153:     sprReg1Bg0YPort = 0;
   154:     sprReg1Bg0YMask = 0;
   155:     sprReg1Bg0YTest = 0;
   156:     sprReg1Bg0YCurr = 0;
   157:     sprReg2Bg1XPort = 0;
   158:     sprReg2Bg1XMask = 0;
   159:     sprReg2Bg1XTest = 0;
   160:     sprReg2Bg1XCurr = 0;
   161:     sprReg3Bg1YPort = 0;
   162:     sprReg3Bg1YMask = 0;
   163:     sprReg3Bg1YTest = 0;
   164:     sprReg3Bg1YCurr = 0;
   165:     sprReg4BgCtrlPort = 0;
   166:     sprReg4BgCtrlMask = 0;
   167:     sprReg4BgCtrlTest = 0;
   168:     sprReg4BgCtrlCurr = 0;
   169:     sprReg5HTotalPort = 0;
   170:     sprReg5HTotalMask = 0;
   171:     sprReg5HTotalTest = 0;
   172:     sprReg5HTotalCurr = 0;
   173:     sprReg6HStartPort = 0;
   174:     sprReg6HStartMask = 0;
   175:     sprReg6HStartTest = 0;
   176:     sprReg6HStartCurr = 0;
   177:     sprReg7VStartPort = 0;
   178:     sprReg7VStartMask = 0;
   179:     sprReg7VStartTest = 0;
   180:     sprReg7VStartCurr = 0;
   181:     sprReg8ResoPort = 0;
   182:     sprReg8ResoMask = 0;
   183:     sprReg8ResoTest = 0;
   184:     sprReg8ResoCurr = 0;
   185:     //sprX = new short[128];
   186:     //sprY = new short[128];
   187:     //sprNum = new short[128];
   188:     //sprColPort = new short[128];
   189:     //sprPrw = new byte[128];
   190:     //sprH = new boolean[128];
   191:     //sprV = new boolean[128];
   192:     if (SPR_RRMAP) {
   193:       //sprRRmap = new int[1039 << 2];
   194:       //sprPPmap = new int[256 << 2];
   195:     } else {
   196:       //sprRmap = new int[4][];
   197:       //sprRmap[0] = sprRmap0 = new int[1039];
   198:       //sprRmap[1] = sprRmap1 = new int[1039];
   199:       //sprRmap[2] = sprRmap2 = new int[1039];
   200:       //sprRmap[3] = sprRmap3 = new int[1039];
   201:       //sprPmap = new int[4][];
   202:       //sprPmap[0] = sprPmap0 = new int[256];
   203:       //sprPmap[1] = sprPmap1 = new int[256];
   204:       //sprPmap[2] = sprPmap2 = new int[256];
   205:       //sprPmap[3] = sprPmap3 = new int[256];
   206:     }
   207:     //sprT0Num = new short[4096];
   208:     //sprT0ColPort = new short[4096];
   209:     //sprT0H = new boolean[4096];
   210:     //sprT0V = new boolean[4096];
   211:     //sprT1Num = new short[4096];
   212:     //sprT1ColPort = new short[4096];
   213:     //sprT1H = new boolean[4096];
   214:     //sprT1V = new boolean[4096];
   215: 
   216:     if (SPR_THREE_STEPS) {
   217:       sprBuffer = new int[1056 * 2];
   218:       sprShadowBuffer = new int[1056 * 2];
   219:     }
   220: 
   221:     //sprPatPort = new int[8192];
   222:     //パターンテスト
   223:     if (SPR_PATTEST_ON) {
   224:       //スプライトパターン
   225:       //sprPatTest = new int[8192];
   226:       Arrays.fill (sprPatTest, 0x00000000);
   227:       //  BGに0番が並んでいるときBGが手前にあるとスプライトが見えにくくなるので0番は上下左右の反転を示す印だけにする
   228:       if (SPR_PATTEST_MARK == '^') {
   229:         sprPatTest[ 5] = 0x01000000;
   230:         sprPatTest[ 6] = 0x10100000;
   231:         sprPatTest[13] = 0x02000000;
   232:         sprPatTest[14] = 0x20200000;
   233:         sprPatTest[21] = 0x03000000;
   234:         sprPatTest[22] = 0x30300000;
   235:         sprPatTest[29] = 0x04000000;
   236:         sprPatTest[30] = 0x40400000;
   237:       } else if (SPR_PATTEST_MARK == '~') {
   238:         sprPatTest[ 6] = 0x11100000;
   239:         sprPatTest[14] = 0x22200000;
   240:         sprPatTest[22] = 0x33300000;
   241:         sprPatTest[30] = 0x44400000;
   242:       } else if (SPR_PATTEST_MARK == '¨') {
   243:         sprPatTest[ 6] = 0x10100000;
   244:         sprPatTest[14] = 0x20200000;
   245:         sprPatTest[22] = 0x30300000;
   246:         sprPatTest[30] = 0x40400000;
   247:       } else if (SPR_PATTEST_MARK == '˙') {
   248:         sprPatTest[ 6] = 0x01000000;
   249:         sprPatTest[14] = 0x02000000;
   250:         sprPatTest[22] = 0x03000000;
   251:         sprPatTest[30] = 0x04000000;
   252:       }
   253:       for (int i = 32; i < 8192; i += 32) {
   254:         int x1 = i >> 9 & 15;  //上位4bit
   255:         int x0 = i >> 5 & 15;  //下位4bit
   256:         x1 = Indicator.IND_ASCII_3X5[(9 - x1 >> 4 & 7 | 48) + x1];  //上位3x5dot
   257:         x0 = Indicator.IND_ASCII_3X5[(9 - x0 >> 4 & 7 | 48) + x0];  //下位3x5dot
   258:         int p0 = VideoController.VCN_TXP0[x1 >> 12 - 5 & 0b11100000 | x0 >> 12 - 1 & 0b00001110];
   259:         int p1 = VideoController.VCN_TXP0[x1 >>  9 - 5 & 0b11100000 | x0 >>  9 - 1 & 0b00001110];
   260:         int p2 = VideoController.VCN_TXP0[x1 >>  6 - 5 & 0b11100000 | x0 >>  6 - 1 & 0b00001110];
   261:         int p3 = VideoController.VCN_TXP0[x1 <<  5 - 3 & 0b11100000 | x0 >>  3 - 1 & 0b00001110];
   262:         int p4 = VideoController.VCN_TXP0[x1 <<  5 - 0 & 0b11100000 | x0 <<  1 - 0 & 0b00001110];
   263:         //左上
   264:         sprPatTest[i     ] = p0;
   265:         sprPatTest[i +  1] = p1;
   266:         sprPatTest[i +  2] = p2;
   267:         sprPatTest[i +  3] = p3;
   268:         sprPatTest[i +  4] = p4;
   269:         //左下
   270:         sprPatTest[i +  8] = p0 << 1;
   271:         sprPatTest[i +  9] = p1 << 1;
   272:         sprPatTest[i + 10] = p2 << 1;
   273:         sprPatTest[i + 11] = p3 << 1;
   274:         sprPatTest[i + 12] = p4 << 1;
   275:         //右上
   276:         sprPatTest[i + 16] = p0 * 3;
   277:         sprPatTest[i + 17] = p1 * 3;
   278:         sprPatTest[i + 18] = p2 * 3;
   279:         sprPatTest[i + 19] = p3 * 3;
   280:         sprPatTest[i + 20] = p4 * 3;
   281:         //右下
   282:         sprPatTest[i + 24] = p0 << 2;
   283:         sprPatTest[i + 25] = p1 << 2;
   284:         sprPatTest[i + 26] = p2 << 2;
   285:         sprPatTest[i + 27] = p3 << 2;
   286:         sprPatTest[i + 28] = p4 << 2;
   287:         //上下左右の反転を示す印
   288:         if (SPR_PATTEST_MARK == '^') {
   289:           sprPatTest[i +  5] = 0x01000000;
   290:           sprPatTest[i +  6] = 0x10100000;
   291:           sprPatTest[i + 13] = 0x02000000;
   292:           sprPatTest[i + 14] = 0x20200000;
   293:           sprPatTest[i + 21] = 0x03000000;
   294:           sprPatTest[i + 22] = 0x30300000;
   295:           sprPatTest[i + 29] = 0x04000000;
   296:           sprPatTest[i + 30] = 0x40400000;
   297:         } else if (SPR_PATTEST_MARK == '~') {
   298:           sprPatTest[i +  6] = 0x11100000;
   299:           sprPatTest[i + 14] = 0x22200000;
   300:           sprPatTest[i + 22] = 0x33300000;
   301:           sprPatTest[i + 30] = 0x44400000;
   302:         } else if (SPR_PATTEST_MARK == '¨') {
   303:           sprPatTest[i +  6] = 0x10100000;
   304:           sprPatTest[i + 14] = 0x20200000;
   305:           sprPatTest[i + 22] = 0x30300000;
   306:           sprPatTest[i + 30] = 0x40400000;
   307:         } else if (SPR_PATTEST_MARK == '˙') {
   308:           sprPatTest[i +  6] = 0x01000000;
   309:           sprPatTest[i + 14] = 0x02000000;
   310:           sprPatTest[i + 22] = 0x03000000;
   311:           sprPatTest[i + 30] = 0x04000000;
   312:         }
   313:       }
   314:       //パレットブロック
   315:       //sprColTest = new short[128];
   316:       //sprT0ColTest = new short[4096];
   317:       //sprT1ColTest = new short[4096];
   318:       for (int i = 0; i < 128; i++) {
   319:         sprColTest[i] = (short) (16 + (i * (VideoController.VCN_PATTEST_BLOCKS - 2) >> 7) << 4);  //0..127 -> 0..VideoController.VCN_PATTEST_BLOCKS-3
   320:       }
   321:       Arrays.fill (sprT0ColTest, (short) (16 + VideoController.VCN_PATTEST_BLOCKS - 2 << 4));
   322:       Arrays.fill (sprT1ColTest, (short) (16 + VideoController.VCN_PATTEST_BLOCKS - 1 << 4));
   323:     }  //if SPR_PATTEST_ON
   324:     sprPatCurr = sprPatPort;
   325:     sprColCurr = sprColPort;
   326:     sprT0ColCurr = sprT0ColPort;
   327:     sprT1ColCurr = sprT1ColPort;
   328: 
   329:     sprReset ();
   330:   }  //sprInit()
   331: 
   332:   //sprReset ()
   333:   //  リセット
   334:   public static void sprReset () {
   335:     Arrays.fill (sprX, (short) 0);
   336:     Arrays.fill (sprY, (short) 0);
   337:     Arrays.fill (sprNum, (short) 0);
   338:     Arrays.fill (sprColPort, (short) 0);
   339:     Arrays.fill (sprPrw, (byte) 0);
   340:     Arrays.fill (sprH, false);
   341:     Arrays.fill (sprV, false);
   342:     if (SPR_RRMAP) {
   343:       Arrays.fill (sprRRmap, 0);
   344:     } else {
   345:       Arrays.fill (sprRmap0, 0);
   346:       Arrays.fill (sprRmap1, 0);
   347:       Arrays.fill (sprRmap2, 0);
   348:       Arrays.fill (sprRmap3, 0);
   349:     }
   350:     Arrays.fill (sprPatPort, 0);
   351:     if (SPR_RRMAP) {
   352:       Arrays.fill (sprPPmap, 0);
   353:     } else {
   354:       Arrays.fill (sprPmap0, 0);
   355:       Arrays.fill (sprPmap1, 0);
   356:       Arrays.fill (sprPmap2, 0);
   357:       Arrays.fill (sprPmap3, 0);
   358:     }
   359:     Arrays.fill (sprT0Num, (short) 0);
   360:     Arrays.fill (sprT0ColPort, (short) 0);
   361:     Arrays.fill (sprT0H, false);
   362:     Arrays.fill (sprT0V, false);
   363:     Arrays.fill (sprT1Num, (short) 0);
   364:     Arrays.fill (sprT1ColPort, (short) 0);
   365:     Arrays.fill (sprT1H, false);
   366:     Arrays.fill (sprT1V, false);
   367:   }  //sprReset()
   368: 
   369: 
   370:   //
   371:   //  ノーマル
   372:   //    ラスタ(dst=-2,src=-2)
   373:   //      表(0)にスプライト(0)を並べる
   374:   //      表(0)と裏(-1)を入れ換える
   375:   //    ラスタ(dst=-1,src=-1)
   376:   //      表(-1)を表(1)として再利用する
   377:   //      表(1)にスプライト(1)を並べる
   378:   //      表(1)と裏(0)を入れ換える
   379:   //      表(0)にバックグラウンド(0)を並べる
   380:   //    ラスタ(dst=src)
   381:   //      表(dst)のスプライト(src)とバックグラウンド(src)を重ねる
   382:   //      表(dst)を描画する
   383:   //      表(dst)を表(dst+2)として再利用する
   384:   //      表(dst+2)にスプライト(src+2)を並べる
   385:   //      表(dst+2)と裏(dst+1)を入れ換える
   386:   //      表(dst+1)にバックグラウンド(src+1)を並べる
   387:   //
   388:   //  ラスタ2度読み
   389:   //    偶数ラスタ(dst=-2,src=-1)
   390:   //      表(0)にスプライト(0)を並べる
   391:   //      表(0)と裏(-1)を入れ換える
   392:   //    奇数ラスタ(dst=-1,src=-1)
   393:   //      表(-1)を表(1)として再利用する
   394:   //      表(1)にスプライト(0)を並べる
   395:   //      表(1)と裏(0)を入れ換える
   396:   //      表(0)にバックグラウンド(0)を並べる
   397:   //    偶数ラスタ(dst=src*2)
   398:   //      表(dst)のスプライト(src)とバックグラウンド(src)を重ねる
   399:   //      表(dst)を描画する
   400:   //      表(dst)を表(dst+2)として再利用する
   401:   //      表(dst+2)にスプライト(src+1)を並べる
   402:   //      表(dst+2)と裏(dst+1)を入れ換える
   403:   //      表(dst+1)にバックグラウンド(src)を並べる
   404:   //    奇数ラスタ(dst=src*2+1)
   405:   //      表(dst)のスプライト(src)とバックグラウンド(src)を重ねる
   406:   //      表(dst)を描画する
   407:   //      表(dst)を表(dst+2)として再利用する
   408:   //      表(dst+2)にスプライト(src+1)を並べる
   409:   //      表(dst+2)と裏(dst+1)を入れ換える
   410:   //      表(dst+1)にバックグラウンド(src+1)を並べる
   411:   //
   412:   //  インタレース
   413:   //    ラスタ(dst=-4,src=-4)
   414:   //      表(0)にスプライト(0)を並べる
   415:   //      表(0)と裏(-2)を入れ換える
   416:   //    ラスタ(dst=-2,src=-2)
   417:   //      表(-2)を表(2)として再利用する
   418:   //      表(2)にスプライト(2)を並べる
   419:   //      表(2)と裏(0)を入れ換える
   420:   //      表(0)にバックグラウンド(0)を並べる
   421:   //    ラスタ(dst=src)
   422:   //      表(dst)のスプライト(src)とバックグラウンド(src)を重ねる
   423:   //      表(dst)を描画する
   424:   //      表(dst)を表(dst+4)として再利用する
   425:   //      表(dst+4)にスプライト(src+4)を並べる
   426:   //      表(dst+4)と裏(dst+2)を入れ換える
   427:   //      表(dst+2)にバックグラウンド(src+2)を並べる
   428:   //
   429:   //  スリット
   430:   //    ラスタ(dst=-4,src=-2)
   431:   //      表(0)にスプライト(0)を並べる
   432:   //      表(0)と裏(-2)を入れ換える
   433:   //    ラスタ(dst=-2,src=-1)
   434:   //      表(-2)を表(2)として再利用する
   435:   //      表(2)にスプライト(1)を並べる
   436:   //      表(2)と裏(0)を入れ換える
   437:   //      表(0)にバックグラウンド(0)を並べる
   438:   //    ラスタ(dst=src*2)
   439:   //      表(dst)のスプライト(src)とバックグラウンド(src)を重ねる
   440:   //      表(dst)を描画する
   441:   //      表(dst)を表(dst+4)として再利用する
   442:   //      表(dst+4)にスプライト(src+2)を並べる
   443:   //      表(dst+4)と裏(dst+2)を入れ換える
   444:   //      表(dst+2)にバックグラウンド(src+1)を並べる
   445:   //
   446: 
   447:   //sprSwap ()
   448:   //  表と裏を入れ換える
   449:   //
   450:   //!!! if (SPR_THREE_STEPS)
   451:   public static void sprSwap () {
   452:     int[] t = sprBuffer;
   453:     sprBuffer = sprShadowBuffer;
   454:     sprShadowBuffer = t;
   455:   }  //sprSwap()
   456: 
   457:   //sprStep1 (src)
   458:   //  スプライトを並べる
   459:   //
   460:   //  sprBuffer[x]
   461:   //    4bitパレット
   462:   //             28  24  20  16  12   8   4   0
   463:   //    手前← |---|SP3|BG0|SP2|BG1|SP1|---|---| →奥
   464:   //
   465:   //  sprBuffer[1056 + x]
   466:   //    パレットブロック
   467:   //             28  24  20  16  12   8   4   0
   468:   //    手前← |---|SP3|BG0|SP2|BG1|SP1|---|---| →奥
   469:   //
   470:   //!!! if (SPR_THREE_STEPS)
   471:   //!!! if (SPR_RRMAP)
   472:   public static void sprStep1 (int src) {
   473:     //バッファをクリアする
   474:     //  4bitパレットとパレットブロックの両方をクリアすること
   475:     Arrays.fill (sprBuffer, 0);
   476:     //垂直映像開始位置の指定に伴う補正
   477:     src += sprReg7VStartCurr - CRTC.crtR06VBackEndCurr;
   478:     if (src < 0 || 1023 < src) {
   479:       return;
   480:     }
   481:     //水平映像開始位置の指定に伴う補正
   482:     int hStart = (sprReg6HStartCurr - CRTC.crtR02HBackEndCurr - 4) << 3;
   483:     int width16 = 16 + XEiJ.pnlScreenWidth;
   484:     int cnt = 0;  //ラスタにかかっているスプライトの数
   485:   nn:
   486:     for (int i = 16 + src << 2, nn = 0; nn <= 128 - 32; nn += 32) {
   487:       for (int map = sprRRmap[i++], n = nn; map != 0; map <<= 1, n++) {  //nは昇順
   488:         if (map >= 0) {  //このスプライトはラスタにかかっていない
   489:           continue;
   490:         }
   491:         int x = hStart + sprX[n];  //X座標。画面左端は16
   492:         if (x <= 0 || width16 <= x) {  //画面外。画面外のスプライトは水平表示限界に影響しない
   493:           continue;
   494:         }
   495:         //  8x8のパターンを
   496:         //    +---+---+
   497:         //    | 0 | 2 |
   498:         //    +---+---+
   499:         //    | 1 | 3 |
   500:         //    +---+---+
   501:         //  の順序で並べる
   502:         int a = (sprNum[n] << 5) + (sprV[n] ? sprY[n] - src - 1 : 16 + src - sprY[n]);
   503:         int prw = sprPrw[n] << 3;  //プライオリティ*8。表示されていることがわかっているのでプライオリティは1~3のいずれかであるはず
   504:         int col = sprColCurr[n] << prw >>> 4;  //パレットブロック
   505:         int s, t;
   506:         if ((t = sprPatCurr[a]) != 0) {  //左半分のパターンあり
   507:           if (sprH[n]) {  //水平反転あり。左半分→右半分
   508:             if ((s = 15       & t) != 0 && sprBuffer[ 8 + x] >>> prw == 0) {  //ドットがありかつ若い番号のスプライトよりも優先順位が高い
   509:               sprBuffer[        8 + x] = s        << prw;
   510:               sprBuffer[1056 +  8 + x] = col;
   511:             }
   512:             if ((s = 15 <<  4 & t) != 0 && sprBuffer[ 9 + x] >>> prw == 0) {  //ドットがありかつ若い番号のスプライトよりも優先順位が高い
   513:               sprBuffer[        9 + x] = s >>>  4 << prw;
   514:               sprBuffer[1056 +  9 + x] = col;
   515:             }
   516:             if ((s = 15 <<  8 & t) != 0 && sprBuffer[10 + x] >>> prw == 0) {  //ドットがありかつ若い番号のスプライトよりも優先順位が高い
   517:               sprBuffer[       10 + x] = s >>>  8 << prw;
   518:               sprBuffer[1056 + 10 + x] = col;
   519:             }
   520:             if ((s = 15 << 12 & t) != 0 && sprBuffer[11 + x] >>> prw == 0) {  //ドットがありかつ若い番号のスプライトよりも優先順位が高い
   521:               sprBuffer[       11 + x] = s >>> 12 << prw;
   522:               sprBuffer[1056 + 11 + x] = col;
   523:             }
   524:             if ((s = 15 << 16 & t) != 0 && sprBuffer[12 + x] >>> prw == 0) {  //ドットがありかつ若い番号のスプライトよりも優先順位が高い
   525:               sprBuffer[       12 + x] = s >>> 16 << prw;
   526:               sprBuffer[1056 + 12 + x] = col;
   527:             }
   528:             if ((s = 15 << 20 & t) != 0 && sprBuffer[13 + x] >>> prw == 0) {  //ドットがありかつ若い番号のスプライトよりも優先順位が高い
   529:               sprBuffer[       13 + x] = s >>> 20 << prw;
   530:               sprBuffer[1056 + 13 + x] = col;
   531:             }
   532:             if ((s = 15 << 24 & t) != 0 && sprBuffer[14 + x] >>> prw == 0) {  //ドットがありかつ若い番号のスプライトよりも優先順位が高い
   533:               sprBuffer[       14 + x] = s >>> 24 << prw;
   534:               sprBuffer[1056 + 14 + x] = col;
   535:             }
   536:             if ((s = t >>> 28    ) != 0 && sprBuffer[15 + x] >>> prw == 0) {  //ドットがありかつ若い番号のスプライトよりも優先順位が高い
   537:               sprBuffer[       15 + x] = s        << prw;
   538:               sprBuffer[1056 + 15 + x] = col;
   539:             }
   540:           } else {  //水平反転なし。左半分→左半分
   541:             if ((s = t >>> 28    ) != 0 && sprBuffer[     x] >>> prw == 0) {  //ドットがありかつ若い番号のスプライトよりも優先順位が高い
   542:               sprBuffer[            x] = s        << prw;
   543:               sprBuffer[1056      + x] = col;
   544:             }
   545:             if ((s = 15 << 24 & t) != 0 && sprBuffer[ 1 + x] >>> prw == 0) {  //ドットがありかつ若い番号のスプライトよりも優先順位が高い
   546:               sprBuffer[        1 + x] = s >>> 24 << prw;
   547:               sprBuffer[1056 +  1 + x] = col;
   548:             }
   549:             if ((s = 15 << 20 & t) != 0 && sprBuffer[ 2 + x] >>> prw == 0) {  //ドットがありかつ若い番号のスプライトよりも優先順位が高い
   550:               sprBuffer[        2 + x] = s >>> 20 << prw;
   551:               sprBuffer[1056 +  2 + x] = col;
   552:             }
   553:             if ((s = 15 << 16 & t) != 0 && sprBuffer[ 3 + x] >>> prw == 0) {  //ドットがありかつ若い番号のスプライトよりも優先順位が高い
   554:               sprBuffer[        3 + x] = s >>> 16 << prw;
   555:               sprBuffer[1056 +  3 + x] = col;
   556:             }
   557:             if ((s = 15 << 12 & t) != 0 && sprBuffer[ 4 + x] >>> prw == 0) {  //ドットがありかつ若い番号のスプライトよりも優先順位が高い
   558:               sprBuffer[        4 + x] = s >>> 12 << prw;
   559:               sprBuffer[1056 +  4 + x] = col;
   560:             }
   561:             if ((s = 15 <<  8 & t) != 0 && sprBuffer[ 5 + x] >>> prw == 0) {  //ドットがありかつ若い番号のスプライトよりも優先順位が高い
   562:               sprBuffer[        5 + x] = s >>>  8 << prw;
   563:               sprBuffer[1056 +  5 + x] = col;
   564:             }
   565:             if ((s = 15 <<  4 & t) != 0 && sprBuffer[ 6 + x] >>> prw == 0) {  //ドットがありかつ若い番号のスプライトよりも優先順位が高い
   566:               sprBuffer[        6 + x] = s >>>  4 << prw;
   567:               sprBuffer[1056 +  6 + x] = col;
   568:             }
   569:             if ((s = 15       & t) != 0 && sprBuffer[ 7 + x] >>> prw == 0) {  //ドットがありかつ若い番号のスプライトよりも優先順位が高い
   570:               sprBuffer[        7 + x] = s        << prw;
   571:               sprBuffer[1056 +  7 + x] = col;
   572:             }
   573:           }  //if 水平反転あり/水平反転なし
   574:         }  //if 左半分のパターンあり
   575:         if ((t = sprPatCurr[16 + a]) != 0) {  //右半分のパターンあり
   576:           if (sprH[n]) {  //水平反転あり。右半分→左半分
   577:             if ((s = 15       & t) != 0 && sprBuffer[     x] >>> prw == 0) {  //ドットがありかつ若い番号のスプライトよりも優先順位が高い
   578:               sprBuffer[            x] = s        << prw;
   579:               sprBuffer[1056      + x] = col;
   580:             }
   581:             if ((s = 15 <<  4 & t) != 0 && sprBuffer[ 1 + x] >>> prw == 0) {  //ドットがありかつ若い番号のスプライトよりも優先順位が高い
   582:               sprBuffer[        1 + x] = s >>>  4 << prw;
   583:               sprBuffer[1056 +  1 + x] = col;
   584:             }
   585:             if ((s = 15 <<  8 & t) != 0 && sprBuffer[ 2 + x] >>> prw == 0) {  //ドットがありかつ若い番号のスプライトよりも優先順位が高い
   586:               sprBuffer[        2 + x] = s >>>  8 << prw;
   587:               sprBuffer[1056 +  2 + x] = col;
   588:             }
   589:             if ((s = 15 << 12 & t) != 0 && sprBuffer[ 3 + x] >>> prw == 0) {  //ドットがありかつ若い番号のスプライトよりも優先順位が高い
   590:               sprBuffer[        3 + x] = s >>> 12 << prw;
   591:               sprBuffer[1056 +  3 + x] = col;
   592:             }
   593:             if ((s = 15 << 16 & t) != 0 && sprBuffer[ 4 + x] >>> prw == 0) {  //ドットがありかつ若い番号のスプライトよりも優先順位が高い
   594:               sprBuffer[        4 + x] = s >>> 16 << prw;
   595:               sprBuffer[1056 +  4 + x] = col;
   596:             }
   597:             if ((s = 15 << 20 & t) != 0 && sprBuffer[ 5 + x] >>> prw == 0) {  //ドットがありかつ若い番号のスプライトよりも優先順位が高い
   598:               sprBuffer[        5 + x] = s >>> 20 << prw;
   599:               sprBuffer[1056 +  5 + x] = col;
   600:             }
   601:             if ((s = 15 << 24 & t) != 0 && sprBuffer[ 6 + x] >>> prw == 0) {  //ドットがありかつ若い番号のスプライトよりも優先順位が高い
   602:               sprBuffer[        6 + x] = s >>> 24 << prw;
   603:               sprBuffer[1056 +  6 + x] = col;
   604:             }
   605:             if ((s = t >>> 28    ) != 0 && sprBuffer[ 7 + x] >>> prw == 0) {  //ドットがありかつ若い番号のスプライトよりも優先順位が高い
   606:               sprBuffer[        7 + x] = s        << prw;
   607:               sprBuffer[1056 +  7 + x] = col;
   608:             }
   609:           } else {  //水平反転なし。右半分→右半分
   610:             if ((s = t >>> 28    ) != 0 && sprBuffer[ 8 + x] >>> prw == 0) {  //ドットがありかつ若い番号のスプライトよりも優先順位が高い
   611:               sprBuffer[        8 + x] = s        << prw;
   612:               sprBuffer[1056  + 8 + x] = col;
   613:             }
   614:             if ((s = 15 << 24 & t) != 0 && sprBuffer[ 9 + x] >>> prw == 0) {  //ドットがありかつ若い番号のスプライトよりも優先順位が高い
   615:               sprBuffer[        9 + x] = s >>> 24 << prw;
   616:               sprBuffer[1056 +  9 + x] = col;
   617:             }
   618:             if ((s = 15 << 20 & t) != 0 && sprBuffer[10 + x] >>> prw == 0) {  //ドットがありかつ若い番号のスプライトよりも優先順位が高い
   619:               sprBuffer[       10 + x] = s >>> 20 << prw;
   620:               sprBuffer[1056 + 10 + x] = col;
   621:             }
   622:             if ((s = 15 << 16 & t) != 0 && sprBuffer[11 + x] >>> prw == 0) {  //ドットがありかつ若い番号のスプライトよりも優先順位が高い
   623:               sprBuffer[       11 + x] = s >>> 16 << prw;
   624:               sprBuffer[1056 + 11 + x] = col;
   625:             }
   626:             if ((s = 15 << 12 & t) != 0 && sprBuffer[12 + x] >>> prw == 0) {  //ドットがありかつ若い番号のスプライトよりも優先順位が高い
   627:               sprBuffer[       12 + x] = s >>> 12 << prw;
   628:               sprBuffer[1056 + 12 + x] = col;
   629:             }
   630:             if ((s = 15 <<  8 & t) != 0 && sprBuffer[13 + x] >>> prw == 0) {  //ドットがありかつ若い番号のスプライトよりも優先順位が高い
   631:               sprBuffer[       13 + x] = s >>>  8 << prw;
   632:               sprBuffer[1056 + 13 + x] = col;
   633:             }
   634:             if ((s = 15 <<  4 & t) != 0 && sprBuffer[14 + x] >>> prw == 0) {  //ドットがありかつ若い番号のスプライトよりも優先順位が高い
   635:               sprBuffer[       14 + x] = s >>>  4 << prw;
   636:               sprBuffer[1056 + 14 + x] = col;
   637:             }
   638:             if ((s = 15       & t) != 0 && sprBuffer[15 + x] >>> prw == 0) {  //ドットがありかつ若い番号のスプライトよりも優先順位が高い
   639:               sprBuffer[       15 + x] = s        << prw;
   640:               sprBuffer[1056 + 15 + x] = col;
   641:             }
   642:           }  //if 水平反転あり/水平反転なし
   643:         }  //if 右半分のパターンあり
   644:         if (SPR_HORIZONTAL_LIMIT != 0) {
   645:           if (++cnt == SPR_HORIZONTAL_LIMIT) {  //今回のスプライトで終わりにする
   646:             break nn;
   647:           }
   648:         }
   649:       }  //for map,n
   650:     }  // for i,nn
   651:   }  //sprStep1(int)
   652: 
   653:   //sprStep2 (src)
   654:   //  バックグラウンドを並べる
   655:   //
   656:   //  sprBuffer[x]
   657:   //    4bitパレット
   658:   //             28  24  20  16  12   8   4   0
   659:   //    手前← |---|SP3|BG0|SP2|BG1|SP1|---|---| →奥
   660:   //
   661:   //  sprBuffer[1056 + x]
   662:   //    パレットブロック
   663:   //             28  24  20  16  12   8   4   0
   664:   //    手前← |---|SP3|BG0|SP2|BG1|SP1|---|---| →奥
   665:   //
   666:   //!!! if (SPR_THREE_STEPS)
   667:   public static void sprStep2 (int src) {
   668:     //垂直映像開始位置の指定に伴う補正
   669:     src += sprReg7VStartCurr - CRTC.crtR06VBackEndCurr;
   670:     if (src < 0 || 1023 < src) {
   671:       return;
   672:     }
   673:     //水平映像開始位置の指定に伴う補正
   674:     int hStart = (sprReg6HStartCurr - CRTC.crtR02HBackEndCurr - 4) << 3;
   675:     int width16 = 16 + XEiJ.pnlScreenWidth;
   676:     if ((sprReg8ResoCurr & 3) == 0) {  //水平256ドット、BGパターンは8x8、BG仮想画面は512x512、BG0とBG1
   677:       short[] tnum, tcol;
   678:       boolean[] th, tv;
   679:       int x, y, sx, sy;
   680:       //BG0
   681:       //  BG0の有無は表示ラスタまで分からないので1ラスタ手前では常に展開しておなかければならない
   682:       if ((sprReg4BgCtrlCurr & 3 << 1) == 0) {  //BG0にTEXT0が割り当てられている
   683:         tnum = sprT0Num;  //パターン番号
   684:         tcol = sprT0ColCurr;  //パレットブロック<<4
   685:         th = sprT0H;  //水平反転
   686:         tv = sprT0V;  //垂直反転
   687:       } else {  //BG0にTEXT1が割り当てられている
   688:         tnum = sprT1Num;  //パターン番号
   689:         tcol = sprT1ColCurr;  //パレットブロック<<4
   690:         th = sprT1H;  //水平反転
   691:         tv = sprT1V;  //垂直反転
   692:       }
   693:       x = 16 + hStart - sprReg0Bg0XCurr;  //X座標。画面左端は16
   694:       y = src + sprReg1Bg0YCurr & 511;
   695:       sx = ((x & 7) - x >> 3) & 63;  //テキストX座標
   696:       sy = y >> 3 << 6;  //テキストY座標*64
   697:       x &= 7;
   698:       y &= 7;
   699:       while (x < width16) {
   700:         int t;
   701:         if ((t = sprPatCurr[tnum[sy + sx] + (tv[sy + sx] ? 7 - y : y)]) != 0) {  //パターンあり
   702:           if (th[sy + sx]) {  //水平反転あり
   703:             sprBuffer[     x] |= (t        & 15) << 20;
   704:             sprBuffer[ 1 + x] |= (t >>>  4 & 15) << 20;
   705:             sprBuffer[ 2 + x] |= (t >>>  8 & 15) << 20;
   706:             sprBuffer[ 3 + x] |= (t >>> 12 & 15) << 20;
   707:             sprBuffer[ 4 + x] |= (t >>> 16 & 15) << 20;
   708:             sprBuffer[ 5 + x] |= (t >>> 20 & 15) << 20;
   709:             sprBuffer[ 6 + x] |= (t >>> 24 & 15) << 20;
   710:             sprBuffer[ 7 + x] |= (t >>> 28     ) << 20;
   711:           } else {  //水平反転なし
   712:             sprBuffer[     x] |= (t >>> 28     ) << 20;
   713:             sprBuffer[ 1 + x] |= (t >>> 24 & 15) << 20;
   714:             sprBuffer[ 2 + x] |= (t >>> 20 & 15) << 20;
   715:             sprBuffer[ 3 + x] |= (t >>> 16 & 15) << 20;
   716:             sprBuffer[ 4 + x] |= (t >>> 12 & 15) << 20;
   717:             sprBuffer[ 5 + x] |= (t >>>  8 & 15) << 20;
   718:             sprBuffer[ 6 + x] |= (t >>>  4 & 15) << 20;
   719:             sprBuffer[ 7 + x] |= (t        & 15) << 20;
   720:           }  //if 水平反転あり/水平反転なし
   721:         }  //if パターンあり
   722:         if ((t = tcol[sy + sx]) != 0) {  //パレットブロックが0でないとき。バックグラウンドは4bitパレットが0でもパレットブロックが必要
   723:           t <<= 20 - 4;  //tcolはパレットブロック<<4。ここでは4bitパレットと同じ位置に置く
   724:           sprBuffer[1056      + x] |= t;
   725:           sprBuffer[1056 +  1 + x] |= t;
   726:           sprBuffer[1056 +  2 + x] |= t;
   727:           sprBuffer[1056 +  3 + x] |= t;
   728:           sprBuffer[1056 +  4 + x] |= t;
   729:           sprBuffer[1056 +  5 + x] |= t;
   730:           sprBuffer[1056 +  6 + x] |= t;
   731:           sprBuffer[1056 +  7 + x] |= t;
   732:         }
   733:         x += 8;
   734:         sx = sx + 1 & 63;
   735:       }  //while x<width16
   736:       //BG1
   737:       //  BG1の有無は表示ラスタまで分からないので1ラスタ手前では常に展開しておなかければならない
   738:       if ((sprReg4BgCtrlCurr & 3 << 4) == 0) {  //BG1にTEXT0が割り当てられている
   739:         tnum = sprT0Num;  //パターン番号
   740:         tcol = sprT0ColCurr;  //パレットブロック<<4
   741:         th = sprT0H;  //水平反転
   742:         tv = sprT0V;  //垂直反転
   743:       } else {  //BG1にTEXT1が割り当てられている
   744:         tnum = sprT1Num;  //パターン番号
   745:         tcol = sprT1ColCurr;  //パレットブロック<<4
   746:         th = sprT1H;  //水平反転
   747:         tv = sprT1V;  //垂直反転
   748:       }
   749:       x = 16 + hStart - sprReg2Bg1XCurr;  //X座標。画面左端は16
   750:       y = src + sprReg3Bg1YCurr & 511;
   751:       sx = ((x & 7) - x >> 3) & 63;  //テキストX座標
   752:       sy = y >> 3 << 6;  //テキストY座標*64
   753:       x &= 7;
   754:       y &= 7;
   755:       while (x < width16) {
   756:         int t;
   757:         if ((t = sprPatCurr[tnum[sy + sx] + (tv[sy + sx] ? 7 - y : y)]) != 0) {  //パターンあり
   758:           if (th[sy + sx]) {  //水平反転あり
   759:             sprBuffer[     x] |= (t        & 15) << 12;
   760:             sprBuffer[ 1 + x] |= (t >>>  4 & 15) << 12;
   761:             sprBuffer[ 2 + x] |= (t >>>  8 & 15) << 12;
   762:             sprBuffer[ 3 + x] |= (t >>> 12 & 15) << 12;
   763:             sprBuffer[ 4 + x] |= (t >>> 16 & 15) << 12;
   764:             sprBuffer[ 5 + x] |= (t >>> 20 & 15) << 12;
   765:             sprBuffer[ 6 + x] |= (t >>> 24 & 15) << 12;
   766:             sprBuffer[ 7 + x] |= (t >>> 28     ) << 12;
   767:           } else {  //水平反転なし
   768:             sprBuffer[     x] |= (t >>> 28     ) << 12;
   769:             sprBuffer[ 1 + x] |= (t >>> 24 & 15) << 12;
   770:             sprBuffer[ 2 + x] |= (t >>> 20 & 15) << 12;
   771:             sprBuffer[ 3 + x] |= (t >>> 16 & 15) << 12;
   772:             sprBuffer[ 4 + x] |= (t >>> 12 & 15) << 12;
   773:             sprBuffer[ 5 + x] |= (t >>>  8 & 15) << 12;
   774:             sprBuffer[ 6 + x] |= (t >>>  4 & 15) << 12;
   775:             sprBuffer[ 7 + x] |= (t        & 15) << 12;
   776:           }  //if 水平反転あり/水平反転なし
   777:         }  //if パターンあり
   778:         if ((t = tcol[sy + sx]) != 0) {  //パレットブロックが0でないとき。バックグラウンドは4bitパレットが0でもパレットブロックが必要
   779:           t <<= 12 - 4;  //tcolはパレットブロック<<4。ここでは4bitパレットと同じ位置に置く
   780:           sprBuffer[1056      + x] |= t;
   781:           sprBuffer[1056 +  1 + x] |= t;
   782:           sprBuffer[1056 +  2 + x] |= t;
   783:           sprBuffer[1056 +  3 + x] |= t;
   784:           sprBuffer[1056 +  4 + x] |= t;
   785:           sprBuffer[1056 +  5 + x] |= t;
   786:           sprBuffer[1056 +  6 + x] |= t;
   787:           sprBuffer[1056 +  7 + x] |= t;
   788:         }
   789:         x += 8;
   790:         sx = sx + 1 & 63;
   791:       }  //while x<width16
   792:     } else {  //水平512ドット、BGパターンは16x16、BG仮想画面は1024x1024、BG0のみ
   793:       short[] tnum, tcol;
   794:       boolean[] th, tv;
   795:       int x, y, sx, sy;
   796:       //BG0
   797:       //  BG0の有無は表示ラスタまで分からないので1ラスタ手前では常に展開しておなかければならない
   798:       if ((sprReg4BgCtrlCurr & 6) == 0) {  //BG0にTEXT0が割り当てられている
   799:         tnum = sprT0Num;  //パターン番号
   800:         tcol = sprT0ColCurr;  //パレットブロック<<4
   801:         th = sprT0H;  //水平反転
   802:         tv = sprT0V;  //垂直反転
   803:       } else {  //BG0にTEXT1が割り当てられている
   804:         tnum = sprT1Num;  //パターン番号
   805:         tcol = sprT1ColCurr;  //パレットブロック<<4
   806:         th = sprT1H;  //水平反転
   807:         tv = sprT1V;  //垂直反転
   808:       }
   809:       x = 16 + hStart - sprReg0Bg0XCurr;  //X座標。画面左端は16
   810:       y = src + sprReg1Bg0YCurr & 1023;
   811:       sx = ((x & 15) - x >> 4) & 63;  //テキストX座標
   812:       sy = y >> 4 << 6;  //テキストY座標*64
   813:       x &= 15;
   814:       y &= 15;
   815:       while (x < width16) {
   816:         int a = (tnum[sy + sx] << 2) + (tv[sy + sx] ? 15 - y : y);
   817:         int t;
   818:         if ((t = sprPatCurr[a]) != 0) {  //左半分のパターンあり
   819:           if (th[sy + sx]) {  //水平反転あり。左半分→右半分
   820:             sprBuffer[ 8 + x] |= (t        & 15) << 20;
   821:             sprBuffer[ 9 + x] |= (t >>>  4 & 15) << 20;
   822:             sprBuffer[10 + x] |= (t >>>  8 & 15) << 20;
   823:             sprBuffer[11 + x] |= (t >>> 12 & 15) << 20;
   824:             sprBuffer[12 + x] |= (t >>> 16 & 15) << 20;
   825:             sprBuffer[13 + x] |= (t >>> 20 & 15) << 20;
   826:             sprBuffer[14 + x] |= (t >>> 24 & 15) << 20;
   827:             sprBuffer[15 + x] |= (t >>> 28     ) << 20;
   828:           } else {  //水平反転なし。左半分→左半分
   829:             sprBuffer[     x] |= (t >>> 28     ) << 20;
   830:             sprBuffer[ 1 + x] |= (t >>> 24 & 15) << 20;
   831:             sprBuffer[ 2 + x] |= (t >>> 20 & 15) << 20;
   832:             sprBuffer[ 3 + x] |= (t >>> 16 & 15) << 20;
   833:             sprBuffer[ 4 + x] |= (t >>> 12 & 15) << 20;
   834:             sprBuffer[ 5 + x] |= (t >>>  8 & 15) << 20;
   835:             sprBuffer[ 6 + x] |= (t >>>  4 & 15) << 20;
   836:             sprBuffer[ 7 + x] |= (t        & 15) << 20;
   837:           }  //if 水平反転あり/水平反転なし
   838:         }  //if 左半分のパターンあり
   839:         if ((t = sprPatCurr[16 + a]) != 0) {  //右半分のパターンあり
   840:           if (th[sy + sx]) {  //水平反転あり。右半分→左半分
   841:             sprBuffer[     x] |= (t        & 15) << 20;
   842:             sprBuffer[ 1 + x] |= (t >>>  4 & 15) << 20;
   843:             sprBuffer[ 2 + x] |= (t >>>  8 & 15) << 20;
   844:             sprBuffer[ 3 + x] |= (t >>> 12 & 15) << 20;
   845:             sprBuffer[ 4 + x] |= (t >>> 16 & 15) << 20;
   846:             sprBuffer[ 5 + x] |= (t >>> 20 & 15) << 20;
   847:             sprBuffer[ 6 + x] |= (t >>> 24 & 15) << 20;
   848:             sprBuffer[ 7 + x] |= (t >>> 28     ) << 20;
   849:           } else {  //水平反転なし。右半分→右半分
   850:             sprBuffer[ 8 + x] |= (t >>> 28     ) << 20;
   851:             sprBuffer[ 9 + x] |= (t >>> 24 & 15) << 20;
   852:             sprBuffer[10 + x] |= (t >>> 20 & 15) << 20;
   853:             sprBuffer[11 + x] |= (t >>> 16 & 15) << 20;
   854:             sprBuffer[12 + x] |= (t >>> 12 & 15) << 20;
   855:             sprBuffer[13 + x] |= (t >>>  8 & 15) << 20;
   856:             sprBuffer[14 + x] |= (t >>>  4 & 15) << 20;
   857:             sprBuffer[15 + x] |= (t        & 15) << 20;
   858:           }  //if 水平反転あり/水平反転なし
   859:         }  //if 右半分のパターンあり
   860:         if ((t = tcol[sy + sx]) != 0) {  //パレットブロックが0でないとき。バックグラウンドは4bitパレットが0でもパレットブロックが必要
   861:           t <<= 20 - 4;  //tcolはパレットブロック<<4。ここでは4bitパレットと同じ位置に置く
   862:           sprBuffer[1056      + x] |= t;
   863:           sprBuffer[1056 +  1 + x] |= t;
   864:           sprBuffer[1056 +  2 + x] |= t;
   865:           sprBuffer[1056 +  3 + x] |= t;
   866:           sprBuffer[1056 +  4 + x] |= t;
   867:           sprBuffer[1056 +  5 + x] |= t;
   868:           sprBuffer[1056 +  6 + x] |= t;
   869:           sprBuffer[1056 +  7 + x] |= t;
   870:           sprBuffer[1056 +  8 + x] |= t;
   871:           sprBuffer[1056 +  9 + x] |= t;
   872:           sprBuffer[1056 + 10 + x] |= t;
   873:           sprBuffer[1056 + 11 + x] |= t;
   874:           sprBuffer[1056 + 12 + x] |= t;
   875:           sprBuffer[1056 + 13 + x] |= t;
   876:           sprBuffer[1056 + 14 + x] |= t;
   877:           sprBuffer[1056 + 15 + x] |= t;
   878:         }  //if パレットブロックが0でないとき
   879:         x += 16;
   880:         sx = sx + 1 & 63;
   881:       }  //while x<width16
   882:     }  //if 水平256ドット/水平512ドット
   883:   }  //sprStep2(int)
   884: 
   885:   //sprStep3 ()
   886:   //  スプライトとバックグラウンドを重ねる
   887:   //
   888:   //  sprBuffer[x]
   889:   //    4bitパレット
   890:   //             28  24  20  16  12   8   4   0
   891:   //    手前← |---|SP3|BG0|SP2|BG1|SP1|---|---| →奥
   892:   //
   893:   //  sprBuffer[1056 + x]
   894:   //    パレットブロック
   895:   //             28  24  20  16  12   8   4   0
   896:   //    手前← |---|SP3|BG0|SP2|BG1|SP1|---|---| →奥
   897:   //
   898:   //!!! if (SPR_THREE_STEPS)
   899:   public static void sprStep3 () {
   900:     int width16 = 16 + XEiJ.pnlScreenWidth;
   901:     if (!sprActive ||
   902:         (sprReg4BgCtrlCurr & 512) == 0) {  //スプライト画面が表示されていない
   903:       Arrays.fill (sprBuffer, 16, width16, 0);
   904:     } else {  //スプライト画面が表示されている
   905:       int mask = (15 << 24 |  //スプライト(プライオリティ3)
   906:                   15 << 16 |  //スプライト(プライオリティ2)
   907:                   15 << 8 |  //スプライト(プライオリティ1)
   908:                   15 << 20 & -(sprReg4BgCtrlCurr & 1) |  //BG0。スプライト(プライオリティ3)とスプライト(プライオリティ2)の間
   909:                   15 << 12 & -(sprReg4BgCtrlCurr & 8));  //BG1。スプライト(プライオリティ2)とスプライト(プライオリティ1)の間
   910:       for (int x = 16; x < width16; x++) {  //X座標。画面左端は16
   911:         int l = sprBuffer[x];  //4bitパレット
   912:         int h = sprBuffer[1056 + x];  //パレットブロック
   913:         if ((l &= mask) != 0) {  //4bitパレットが0でないプレーンがある
   914:           int i = Integer.numberOfLeadingZeros (l) & -4;  //一番手前にあるものを選ぶ
   915:           sprBuffer[x] = h << i >>> 28 << 4 | l << i >>> 28;  //パレットブロックと4bitパレットを合わせて8bitパレットを作る
   916:         } else if ((h &= mask & (15 << 20 | 15 << 12)) != 0) {  //パレットブロックが0でないバックグラウンドプレーンがある
   917:           int i = Integer.numberOfTrailingZeros (h) & -4;  //一番奥にあるものを選ぶ
   918:           sprBuffer[x] = (h >> i & 15) << 4 | l >> i & 15;  //パレットブロックと4bitパレットを合わせて8bitパレットを作る
   919:         } else {  //4bitパレットとパレットブロックがすべて0
   920:           sprBuffer[x] = 0;
   921:         }
   922:       }  //for x
   923:     }
   924:   }  //sprStep3()
   925: 
   926: 
   927: }  //class SpriteScreen
   928: 
   929: 
   930: