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