SpriteScreen.java
     1: //========================================================================================
     2: //  SpriteScreen.java
     3: //    en:Sprite screen
     4: //    ja:スプライト画面
     5: //  Copyright (C) 2003-2025 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;  //10  XPC1/PCS1
    26:   //                                                            9   0=スプライト画面表示OFF,1=スプライト画面表示ON
    27:   //                                                            5-4 BG1 00=BG1にTEXT0を割り当てる,01=BG1にTEXT1を割り当てる
    28:   //                                                            3   BG1 0=BG1表示OFF,1=BG1表示ON
    29:   //                                                            2-1 BG0 00=BG0にTEXT0を割り当てる,01=BG0にTEXT1を割り当てる
    30:   //                                                            0   BG0 0=BG0表示OFF,1=BG0表示ON
    31:   public static final int SPR_REG5_H_FRONT_END = 0x00eb080a;  //7-0 水平フロントポーチの終了キャラクタ位置
    32:   public static final int SPR_REG6_H_BACK_END  = 0x00eb080c;  //5-0 水平バックポーチの終了キャラクタ位置
    33:   public static final int SPR_REG7_V_BACK_END  = 0x00eb080e;  //7-0 垂直バックポーチの終了ラスタ
    34:   public static final int SPR_REG8_RESO        = 0x00eb0810;  //4   スプライト画面解像度 0=低解像度,1=高解像度
    35:   //                                                            3-2 スプライト画面垂直サイズ 00=256,01=512
    36:   //                                                            1-0 スプライト画面水平サイズ
    37:   //                                                                00=256(BGパターンは8x8,BG仮想画面は512x512)
    38:   //                                                                01=512(BGパターンは16x16,BG仮想画面は1024x1024,BG0のみ)
    39:   //以下は拡張。実機では使えない
    40:   public static final int SPR_REG9_BANK_CONTROL = 0x00eb0812;  //2-0 バンク制御
    41:   public static final int SPR_REG10_BANK_SELECT = 0x00eb0814;  //3-0 バンク選択
    42: 
    43:   //レジスタ
    44:   //  ゼロ拡張
    45:   public static int sprReg0Bg0XPort;
    46:   public static int sprReg0Bg0XMask;
    47:   public static int sprReg0Bg0XTest;
    48:   public static int sprReg0Bg0XCurr;
    49:   public static int sprReg1Bg0YPort;
    50:   public static int sprReg1Bg0YMask;
    51:   public static int sprReg1Bg0YTest;
    52:   public static int sprReg1Bg0YCurr;
    53:   public static int sprReg2Bg1XPort;
    54:   public static int sprReg2Bg1XMask;
    55:   public static int sprReg2Bg1XTest;
    56:   public static int sprReg2Bg1XCurr;
    57:   public static int sprReg3Bg1YPort;
    58:   public static int sprReg3Bg1YMask;
    59:   public static int sprReg3Bg1YTest;
    60:   public static int sprReg3Bg1YCurr;
    61:   public static int sprReg4BgCtrlPort;  //ポートの読み書きに使われる値
    62:   public static int sprReg4BgCtrlMask;  //マスク。0=ポート,1=テスト
    63:   public static int sprReg4BgCtrlTest;  //テストデータ
    64:   public static int sprReg4BgCtrlCurr;  //使用されている値。sprReg4BgCtrlPort & ~sprReg4BgCtrlMask | sprReg4BgCtrlTest & sprReg4BgCtrlMask
    65:   public static int sprReg5HFrontEndPort;
    66:   public static int sprReg5HFrontEndMask;
    67:   public static int sprReg5HFrontEndTest;
    68:   public static int sprReg5HFrontEndCurr;
    69:   public static int sprReg6HBackEndPort;
    70:   public static int sprReg6HBackEndMask;
    71:   public static int sprReg6HBackEndTest;
    72:   public static int sprReg6HBackEndCurr;
    73:   public static int sprReg7VBackEndPort;
    74:   public static int sprReg7VBackEndMask;
    75:   public static int sprReg7VBackEndTest;
    76:   public static int sprReg7VBackEndCurr;
    77:   public static int sprReg8ResoPort;  //ポートの読み書きに使われる値
    78:   public static int sprReg8ResoMask;  //マスク。0=ポート,1=テスト
    79:   public static int sprReg8ResoTest;  //テストデータ
    80:   public static int sprReg8ResoCurr;  //使用されている値。sprReg8ResoPort & ~sprReg8ResoMask | sprReg8ResoTest & sprReg8ResoMask
    81: 
    82:   //スプライトスクロールレジスタ
    83:   public static final int SPR_SHIFT = 10;  //7~/*11*/10
    84:   public static final int SPR_COUNT = 1 << SPR_SHIFT;  //スプライトの枚数(欠番を含む)。128~/*2048*/1024
    85:   public static final short[] sprX = new short[SPR_COUNT];  //x座標(0~1023)
    86:   public static final short[] sprY = new short[SPR_COUNT];  //y座標(0~1023)
    87:   public static final short[] sprNum = new short[SPR_COUNT];  //パターン番号(0~4095)
    88:   public static final short[] sprColPort = new short[SPR_COUNT];  //パレットブロック(0~15)<<4
    89:   public static final byte[] sprPrw = new byte[SPR_COUNT];  //プライオリティ(0~3)
    90:   public static final boolean[] sprH = new boolean[SPR_COUNT];  //左右反転
    91:   public static final boolean[] sprV = new boolean[SPR_COUNT];  //上下反転
    92:   public static final int[] sprF = new int[SPR_COUNT];  //XPC1/PCS1
    93: 
    94:   //ラスタ毎にどのスプライトが含まれているかを示すテーブル
    95:   //  1ラスタあたりSPR_COUNTビット
    96:   //  プライオリティが0のスプライトは含まれない
    97:   //  スプライト座標は1023までで縦16ビットなので1038まで1039ラスタ必要
    98:   //  下からはみ出したスプライトが上から出てくるということはない
    99:   //  [16]が画面上の最初のラスタになるので描画の際に注意すること
   100:   public static final int[] sprRRmap = new int[1039 << (SPR_SHIFT - 5)];
   101: 
   102:   //パターン
   103:   //  1要素に8ピクセル(4*8=32ビット)ずつ入れる
   104:   //  上位が左側のピクセル
   105:   public static final int[] sprPatPort = new int[32 * 4096];
   106: 
   107:   //パターン毎にどのスプライトで使用されているかを示すテーブル
   108:   //  1パターンあたりSPR_COUNTビット
   109:   //  プライオリティが0のスプライトは含まれない
   110:   public static final int[] sprPPmap = new int[4096 << (SPR_SHIFT - 5)];
   111: 
   112:   //テキストエリア
   113:   public static final short[] sprTNum = new short[4096 * 4];  //テキストエリア パターン番号<<3
   114:   public static final short[] sprTColPort = new short[4096 * 4];  //テキストエリア パレットブロック<<4
   115:   public static short[] sprTColCurr;
   116:   public static final boolean[] sprTH = new boolean[4096 * 4];  //テキストエリア 左右反転
   117:   public static final boolean[] sprTV = new boolean[4096 * 4];  //テキストエリア 上下反転。0=しない,15=する
   118: 
   119:   public static final boolean SPR_THREE_STEPS = true;
   120:   public static int[] sprBuffer;  //表バッファ
   121:   public static int[] sprShadowBuffer;  //裏バッファ
   122:   //  reg4|=512のとき
   123:   //    latched=true
   124:   //  垂直映像期間の先頭
   125:   //    active=latched
   126:   //    (reg4&512)==0のとき
   127:   //      latched=false
   128:   //  activeのとき、そのフレームはスプライト画面が構築され、すべてのラスタが描画される
   129:   public static boolean sprLatched;
   130:   public static boolean sprActive;
   131: 
   132:   //パターンテスト
   133:   public static final boolean SPR_PATTEST_ON = true;
   134:   public static final int SPR_PATTEST_MARK = '\u02d9';  //上下左右の反転を示す印。'^'(U+005E;CIRCUMFLEX ACCENT),'~'(U+007E;TILDE),'¨'(U+00A8;DIAERESIS),'˙'(U+02D9;DOT ABOVE)
   135:   public static final int[] sprPatTest = new int[32 * 4096];
   136:   public static int[] sprPatCurr;
   137:   public static final short[] sprColTest = new short[SPR_COUNT];  //パターンテスト用のパレットブロック(Sp)。(16~23)<<4
   138:   public static final short[] sprTColTest = new short[4096 * 4];  //パターンテスト用のパレットブロック(T)。(24~27)<<4
   139:   public static short[] sprColCurr;  //現在のパレットブロック(0~16)<<4
   140: 
   141:   //ラスタあたりのスプライトの枚数
   142:   public static int sprSpritesPerRaster;  //32=標準
   143: 
   144:   //スプライトの枚数
   145:   public static int sprNumberOfSpritesRequest;
   146:   public static int sprNumberOfSprites;  //スプライトの枚数(欠番を含む)。128,256,512,1024/*,2048*/
   147: 
   148:   //4096個のパターン
   149:   //
   150:   //  テキストエリアの移動
   151:   //    テキストエリアを$00EBC000~$00EBFFFFから$00EB4000~$00EB7FFFへ移動させて、テキストエリアを2面使っていてもパターンを256個定義できるようにします。
   152:   //
   153:   //  スプライトエリアとテキストエリアからのパターンの参照
   154:   //    スプライトエリアとテキストエリアを以下のように変更することで、参照できるパターンの数を256個から1024個または4096個に増やします。
   155:   //      スプライトエリア(256個のパターン)
   156:   //        +0  ______XXXXXXXXXX  X:X座標
   157:   //        +2  ______YYYYYYYYYY  Y:Y座標
   158:   //        +4  VH__CCCCNNNNNNNN  V:上下 H:左右 C:パレットブロック N:パターン番号
   159:   //        +6  ______________PP  P:プライオリティ
   160:   //      スプライトエリア(1024個のパターン)
   161:   //        +0  ______XXXXXXXXXX  X:X座標
   162:   //        +2  ______YYYYYYYYYY  Y:Y座標
   163:   //        +4  VHBBCCCCNNNNNNNN  V:上下 H:左右 B:バンク番号 C:パレットブロック N:パターン番号
   164:   //        +6  ______________PP  P:プライオリティ
   165:   //      スプライトエリア(4096個のパターン、反転なし)
   166:   //        +0  ______XXXXXXXXXX  X:X座標
   167:   //        +2  ______YYYYYYYYYY  Y:Y座標
   168:   //        +4  BBBBCCCCNNNNNNNN  B:バンク番号 C:パレットブロック N:パターン番号
   169:   //        +6  ______________PP  P:プライオリティ
   170:   //      スプライトエリア(4096個のパターン、反転あり)
   171:   //        +0  ______XXXXXXXXXX  X:X座標
   172:   //        +2  ______YYYYYYYYYY  Y:Y座標
   173:   //        +4  BBBBCCCCNNNNNNNN  B:バンク番号 C:パレットブロック N:パターン番号
   174:   //        +6  VH____________PP  V:上下 H:左右 P:プライオリティ
   175:   //      テキストエリア(256個のパターン)
   176:   //            VH__CCCCNNNNNNNN  V:上下 H:左右 C:パレットブロック N:パターン番号
   177:   //      テキストエリア(1024個のパターン)
   178:   //            VHBBCCCCNNNNNNNN  V:上下 H:左右 B:バンク番号 C:パレットブロック N:パターン番号
   179:   //      テキストエリア(4096個のパターン)
   180:   //            BBBBCCCCNNNNNNNN  B:バンク番号 C:パレットブロック N:パターン番号
   181:   //    4096個にしたとき上下左右の反転がなくなりますが、パターンを節約する必要がなければ、必要に応じて反転したパターンを定義すればよいと考えられます。
   182:   //    反転の指示をバンク選択に置き換えることで、反転の結果を定義できるようになります。例えば、反転で済ませていたパターンの影の調整が、定義の処理の変更だけで行えます。
   183:   //
   184:   //  パターンエリアの拡張
   185:   //    パターンエリア($00EB8000~$00EBFFFF)をバンク切り替えを用いて16倍に拡張することで、定義できるパターンの数を256個から4096個に増やします。
   186:   //    バンク切り替えの弱点はランダムアクセスですが、1パターンが16または64ワードなので、書き込みが1パターンあたり1ワード増えたとしても影響は限定的と考えられます。
   187:   //
   188:   //  レジスタの追加
   189:   //    バンク制御レジスタ($00EB0812)とバンク選択レジスタ($00EB0814)を追加します。
   190:   //      バンク制御レジスタ($00EB0812)
   191:   //            _____________MMT  M:モード T:移動
   192:   //            モード  パターンの数  スプライトの反転  テキストの反転
   193:   //               0         256            あり             あり
   194:   //               1        1024            あり             あり
   195:   //               2        4096            なし             なし
   196:   //               3        4096            あり             なし
   197:   //            移動  テキストエリアの移動
   198:   //              0          しない
   199:   //              1           する
   200:   //      バンク選択レジスタ($00EB0814)
   201:   //            ____BBBB________  B:バンク番号
   202:   //    0~4095のパターン番号をシフトせずにバンク選択レジスタへ書き込めます。
   203:   //    後のプログラムが誤動作しないように、どちらも使い終わったら0に戻してください。
   204:   //
   205:   //  疑似グラフィック画面
   206:   //    バックグラウンドに4096個のパターンを1個ずつ敷き詰めることで、3枚目の1024x1024ドット16色のグラフィック画面として使うことができます。
   207:   //
   208:   //  テキストエリアに関する補足
   209:   //    移動前のテキストエリアと、パターンエリアのバンク0の後半は、アドレスが同じですが実体が違います。
   210:   //    移動前のテキストエリアへ書き込んだデータは、テキストエリアと、バンク0の後半の両方へ書き込まれます。
   211:   //    移動前のテキストエリアから読み出したデータは、バンク0の後半から読み出されます。
   212:   //    移動後のテキストエリアへ書き込んだデータは、バンク0の後半へ書き込まれていないので、移動前のテキストエリアから読み出せません。
   213:   //    バンク1以上を選択すると、移動前のテキストエリアは見えなくなります。
   214:   //
   215:   //  その他
   216:   //    標準のIOCSコールは4096個のパターンに対応していません。
   217:   //
   218:   public static boolean sprBankOnRequest;
   219:   public static boolean sprBankOn;  //true=4096個のパターンが有効
   220:   public static int sprBankMode;  //モード。0=256個,1=1024個,2=4096個反転なし,3=4096個反転あり
   221:   public static boolean sprBankShifted;  //true=移動あり
   222:   public static int sprBankNumber;  //バンク番号<<8
   223: 
   224:   //768x512でスプライトを表示
   225:   //  CRTCのR20の下位5ビットが%1xx1xのときスプライト画面を表示できないという制限を解除します。
   226:   //  CRTCのR20のビット4,1,0はドットクロック(オシレータと分周比)を選択します。%1xx1xはドットクロックが25MHz以上で、標準の画面モードではCRTMOD 16~19の768x512、1024x424、1024x848、640x480が該当します。
   227:   //  この制限は強く、768x512でスプライト画面を表示したくてもスプライトエリア、パターンエリア、テキストエリアにアクセスしただけでバスエラーが発生してしまい、取り付く島もありません。
   228:   //  この制限を解除することで、768x512のときもスプライト画面を表示できるようになります。
   229:   //  (もちろん、描画バッファの幅が512ドット分しかなければバッファの幅を広げる作業も必要になるでしょう)
   230:   //
   231:   //  IOCS _SP_INITはスプライト画面を表示できないとき-1を返すことになっていますが、標準のIOCS _SP_INITにはCRTCのR20の下位5ビットが%10110のときだけスプライト画面を表示できないと判断するというバグがあり、1024x848、640x480のときIOCS _SP_INITを使うとアクセスできないスプライトスクロールレジスタを初期化しようとしてバスエラーが発生します。このバグはIPLROM 1.6で修正されています。
   232:   //
   233:   public static boolean spr768x512Request;
   234:   public static boolean spr768x512;  //true=制限を解除する
   235:   public static boolean sprAccessible;  //true=スプライト画面を表示できる(CRTCのR20の下位5ビットが%1xx1xでないまたは制限が解除されている)
   236: 
   237:   //512x512でBG1を表示
   238:   //  512x512のときはバックグラウンドを1面しか表示できないという制限を解除します。
   239:   //  256x256のときと同様に512x512のときもバックグラウンドを2面表示できるようになります。
   240:   public static boolean spr512bg1Request;
   241:   public static boolean spr512bg1;  //true=制限を解除する
   242: 
   243:   //ウェイト
   244:   public static final long SPR_WAIT_PATTERN_DISP_0 = XEiJ.TMR_FREQ * 215L / 1000000000L;
   245:   public static final long SPR_WAIT_SPRITE_DISP_0 = XEiJ.TMR_FREQ * 275L / 1000000000L;
   246:   public static final long SPR_WAIT_SPRITE_DISP_1 = XEiJ.TMR_FREQ * 400L / 1000000000L;
   247:   public static final long SPR_WAIT_PATTERN_DISP_1 = XEiJ.TMR_FREQ * 465L / 1000000000L;
   248:   public static long sprWaitSprite;  //スプライトのウェイト
   249:   public static long sprWaitPattern;  //パターンのウェイト
   250: 
   251:   //行スクロールと列スクロール
   252:   //  $00EB2000-$00EB21FF  ワード[64行*4面]  行スクロールレジスタ
   253:   //  $00EB2200-$00EB23FF  ワード[64列*4面]  列スクロールレジスタ
   254:   public static final boolean SPR_RC_SCROLL_ON = true;
   255:   public static boolean sprRcScrollRequest;
   256:   public static boolean sprRcScrollOn;
   257:   public static final int[] sprRowScroll = new int[64 * 4];  //行スクロールレジスタ。10bit
   258:   public static final int[] sprColScroll = new int[64 * 4];  //列スクロールレジスタ。10bit
   259: 
   260:   //sprInit ()
   261:   //  スプライト画面を初期化する
   262:   public static void sprInit () {
   263:     sprReg0Bg0XPort = 0;
   264:     sprReg0Bg0XMask = 0;
   265:     sprReg0Bg0XTest = 0;
   266:     sprReg0Bg0XCurr = 0;
   267:     sprReg1Bg0YPort = 0;
   268:     sprReg1Bg0YMask = 0;
   269:     sprReg1Bg0YTest = 0;
   270:     sprReg1Bg0YCurr = 0;
   271:     sprReg2Bg1XPort = 0;
   272:     sprReg2Bg1XMask = 0;
   273:     sprReg2Bg1XTest = 0;
   274:     sprReg2Bg1XCurr = 0;
   275:     sprReg3Bg1YPort = 0;
   276:     sprReg3Bg1YMask = 0;
   277:     sprReg3Bg1YTest = 0;
   278:     sprReg3Bg1YCurr = 0;
   279:     sprReg4BgCtrlPort = 0;
   280:     sprReg4BgCtrlMask = 0;
   281:     sprReg4BgCtrlTest = 0;
   282:     sprReg4BgCtrlCurr = 0;
   283:     sprReg5HFrontEndPort = 0;
   284:     sprReg5HFrontEndMask = 0;
   285:     sprReg5HFrontEndTest = 0;
   286:     sprReg5HFrontEndCurr = 0;
   287:     sprReg6HBackEndPort = 0;
   288:     sprReg6HBackEndMask = 0;
   289:     sprReg6HBackEndTest = 0;
   290:     sprReg6HBackEndCurr = 0;
   291:     sprReg7VBackEndPort = 0;
   292:     sprReg7VBackEndMask = 0;
   293:     sprReg7VBackEndTest = 0;
   294:     sprReg7VBackEndCurr = 0;
   295:     sprReg8ResoPort = 0;
   296:     sprReg8ResoMask = 0;
   297:     sprReg8ResoTest = 0;
   298:     sprReg8ResoCurr = 0;
   299:     //sprX = new short[SPR_COUNT];
   300:     //sprY = new short[SPR_COUNT];
   301:     //sprNum = new short[SPR_COUNT];
   302:     //sprColPort = new short[SPR_COUNT];
   303:     //sprPrw = new byte[SPR_COUNT];
   304:     //sprH = new boolean[SPR_COUNT];
   305:     //sprV = new boolean[SPR_COUNT];
   306:     //sprF = new int[SPR_COUNT];
   307:     //sprRRmap = new int[1039 << (SPR_SHIFT - 5)];
   308:     //sprPPmap = new int[4096 << (SPR_SHIFT - 5)];
   309:     //sprTNum = new short[4096 * 4];
   310:     //sprTColPort = new short[4096 * 4];
   311:     //sprTH = new boolean[4096 * 4];
   312:     //sprTV = new boolean[4096 * 4];
   313: 
   314:     if (SPR_THREE_STEPS) {
   315:       sprBuffer = new int[1056 * 3];
   316:       sprShadowBuffer = new int[1056 * 3];
   317:     }
   318: 
   319:     //sprPatPort = new int[32 * 4096];
   320:     //パターンテスト
   321:     if (SPR_PATTEST_ON) {
   322:       //スプライトパターン
   323:       //sprPatTest = new int[32 * 4096];
   324:       Arrays.fill (sprPatTest, 0x00000000);
   325:       //  BGに0番が並んでいるときBGが手前にあるとスプライトが見えにくくなるので0番は上下左右の反転を示す印だけにする
   326:       if (SPR_PATTEST_MARK == '^') {
   327:         sprPatTest[ 5] = 0x01000000;
   328:         sprPatTest[ 6] = 0x10100000;
   329:         sprPatTest[13] = 0x02000000;
   330:         sprPatTest[14] = 0x20200000;
   331:         sprPatTest[21] = 0x03000000;
   332:         sprPatTest[22] = 0x30300000;
   333:         sprPatTest[29] = 0x04000000;
   334:         sprPatTest[30] = 0x40400000;
   335:       } else if (SPR_PATTEST_MARK == '~') {
   336:         sprPatTest[ 6] = 0x11100000;
   337:         sprPatTest[14] = 0x22200000;
   338:         sprPatTest[22] = 0x33300000;
   339:         sprPatTest[30] = 0x44400000;
   340:       } else if (SPR_PATTEST_MARK == '¨') {
   341:         sprPatTest[ 6] = 0x10100000;
   342:         sprPatTest[14] = 0x20200000;
   343:         sprPatTest[22] = 0x30300000;
   344:         sprPatTest[30] = 0x40400000;
   345:       } else if (SPR_PATTEST_MARK == '˙') {
   346:         sprPatTest[ 6] = 0x01000000;
   347:         sprPatTest[14] = 0x02000000;
   348:         sprPatTest[22] = 0x03000000;
   349:         sprPatTest[30] = 0x04000000;
   350:       }
   351:       for (int i = 32; i < (32 * 4096); i += 32) {
   352:         int x1 = i >> 9 & 15;  //上位4bit
   353:         int x0 = i >> 5 & 15;  //下位4bit
   354:         x1 = Indicator.IND_ASCII_3X5[(9 - x1 >> 4 & 7 | 48) + x1];  //上位3x5dot
   355:         x0 = Indicator.IND_ASCII_3X5[(9 - x0 >> 4 & 7 | 48) + x0];  //下位3x5dot
   356:         int p0 = VideoController.VCN_TXP0[x1 >> 12 - 5 & 0b11100000 | x0 >> 12 - 1 & 0b00001110];
   357:         int p1 = VideoController.VCN_TXP0[x1 >>  9 - 5 & 0b11100000 | x0 >>  9 - 1 & 0b00001110];
   358:         int p2 = VideoController.VCN_TXP0[x1 >>  6 - 5 & 0b11100000 | x0 >>  6 - 1 & 0b00001110];
   359:         int p3 = VideoController.VCN_TXP0[x1 <<  5 - 3 & 0b11100000 | x0 >>  3 - 1 & 0b00001110];
   360:         int p4 = VideoController.VCN_TXP0[x1 <<  5 - 0 & 0b11100000 | x0 <<  1 - 0 & 0b00001110];
   361:         //左上
   362:         sprPatTest[i     ] = p0;
   363:         sprPatTest[i +  1] = p1;
   364:         sprPatTest[i +  2] = p2;
   365:         sprPatTest[i +  3] = p3;
   366:         sprPatTest[i +  4] = p4;
   367:         //左下
   368:         sprPatTest[i +  8] = p0 << 1;
   369:         sprPatTest[i +  9] = p1 << 1;
   370:         sprPatTest[i + 10] = p2 << 1;
   371:         sprPatTest[i + 11] = p3 << 1;
   372:         sprPatTest[i + 12] = p4 << 1;
   373:         //右上
   374:         sprPatTest[i + 16] = p0 * 3;
   375:         sprPatTest[i + 17] = p1 * 3;
   376:         sprPatTest[i + 18] = p2 * 3;
   377:         sprPatTest[i + 19] = p3 * 3;
   378:         sprPatTest[i + 20] = p4 * 3;
   379:         //右下
   380:         sprPatTest[i + 24] = p0 << 2;
   381:         sprPatTest[i + 25] = p1 << 2;
   382:         sprPatTest[i + 26] = p2 << 2;
   383:         sprPatTest[i + 27] = p3 << 2;
   384:         sprPatTest[i + 28] = p4 << 2;
   385:         //上下左右の反転を示す印
   386:         if (SPR_PATTEST_MARK == '^') {
   387:           sprPatTest[i +  5] = 0x01000000;
   388:           sprPatTest[i +  6] = 0x10100000;
   389:           sprPatTest[i + 13] = 0x02000000;
   390:           sprPatTest[i + 14] = 0x20200000;
   391:           sprPatTest[i + 21] = 0x03000000;
   392:           sprPatTest[i + 22] = 0x30300000;
   393:           sprPatTest[i + 29] = 0x04000000;
   394:           sprPatTest[i + 30] = 0x40400000;
   395:         } else if (SPR_PATTEST_MARK == '~') {
   396:           sprPatTest[i +  6] = 0x11100000;
   397:           sprPatTest[i + 14] = 0x22200000;
   398:           sprPatTest[i + 22] = 0x33300000;
   399:           sprPatTest[i + 30] = 0x44400000;
   400:         } else if (SPR_PATTEST_MARK == '¨') {
   401:           sprPatTest[i +  6] = 0x10100000;
   402:           sprPatTest[i + 14] = 0x20200000;
   403:           sprPatTest[i + 22] = 0x30300000;
   404:           sprPatTest[i + 30] = 0x40400000;
   405:         } else if (SPR_PATTEST_MARK == '˙') {
   406:           sprPatTest[i +  6] = 0x01000000;
   407:           sprPatTest[i + 14] = 0x02000000;
   408:           sprPatTest[i + 22] = 0x03000000;
   409:           sprPatTest[i + 30] = 0x04000000;
   410:         }
   411:       }
   412:       //パレットブロック
   413:       //sprColTest = new short[SPR_COUNT];
   414:       //sprTColTest = new short[4096 * 4];
   415:       for (int i = 0; i < SPR_COUNT; i++) {
   416:         sprColTest[i] = (short) ((16 + ((i & 255) * (VideoController.VCN_PATTEST_BLOCKS - 4) >> 8)) << 4);  //0..255 -> 0..VideoController.VCN_PATTEST_BLOCKS-5
   417:       }
   418:       for (int i = 0; i < 4; i++) {
   419:         Arrays.fill (sprTColTest, i << 12, (i + 1) << 12,
   420:                      (short) ((16 + VideoController.VCN_PATTEST_BLOCKS - 4 + i) << 4));
   421:       }
   422:     }  //if SPR_PATTEST_ON
   423:     sprPatCurr = sprPatPort;
   424:     sprColCurr = sprColPort;
   425:     sprTColCurr = sprTColPort;
   426: 
   427:     //ラスタあたりのスプライトの枚数
   428:     sprSpritesPerRaster = Math.max (0, Math.min (/*2040*/1016, Settings.sgsGetInt ("sprras")));
   429: 
   430:     //スプライトの枚数
   431:     {
   432:       int n = Settings.sgsGetInt ("numspr");
   433:       n = (n == 128 || n == 256 ? n :
   434:            n == 504 || n == 1016 /*|| n == 2040 */? n + 8 :
   435:            128);
   436:       if (n == 128 && Settings.sgsGetOnOff ("dblspr")) {
   437:         n = 256;
   438:       }
   439:       sprNumberOfSpritesRequest = n;
   440:     }
   441: 
   442:     //4096個のパターン
   443:     sprBankOnRequest = Settings.sgsGetOnOff ("sprbank");
   444: 
   445:     //768x512でスプライトを表示
   446:     spr768x512Request = Settings.sgsGetOnOff ("spr768x512");
   447: 
   448:     //512x512でBG1を表示
   449:     spr512bg1Request = Settings.sgsGetOnOff ("spr512bg1");
   450: 
   451:     //ウェイト
   452:     sprWaitSprite = SPR_WAIT_SPRITE_DISP_0;
   453:     sprWaitPattern = SPR_WAIT_PATTERN_DISP_0;
   454: 
   455:     if (SPR_RC_SCROLL_ON) {
   456:       //行スクロールと列スクロール
   457:       sprRcScrollRequest = Settings.sgsGetOnOff ("sprrcscroll");
   458:       //sprRowScroll = new int[64 * 4];
   459:       //sprColScroll = new int[64 * 4];
   460:     }
   461: 
   462:     sprReset ();
   463:   }  //sprInit()
   464: 
   465:   public static void sprTini () {
   466:     //ラスタあたりのスプライトの枚数
   467:     Settings.sgsPutInt ("sprras", sprSpritesPerRaster);
   468:     //スプライトの枚数
   469:     Settings.sgsPutOnOff ("dblspr", false);
   470:     Settings.sgsPutInt ("numspr", sprNumberOfSpritesRequest <= 256 ? sprNumberOfSpritesRequest : sprNumberOfSpritesRequest - 8);
   471:     //4096個のパターン
   472:     Settings.sgsPutOnOff ("sprbank", sprBankOnRequest);
   473:     //768x512でスプライトを表示
   474:     Settings.sgsPutOnOff ("spr768x512", spr768x512Request);
   475:     //512x512でBG1を表示
   476:     Settings.sgsPutOnOff ("spr512bg1", spr512bg1Request);
   477:     if (SPR_RC_SCROLL_ON) {
   478:       //行スクロールと列スクロール
   479:       Settings.sgsPutOnOff ("sprrcscroll", sprRcScrollRequest);
   480:     }
   481:   }
   482: 
   483:   //sprReset ()
   484:   //  リセット
   485:   public static void sprReset () {
   486:     //スプライトの枚数
   487:     sprNumberOfSprites = sprNumberOfSpritesRequest;
   488:     //4096個のパターン
   489:     sprBankOn = sprBankOnRequest;
   490:     sprBankMode = 0;
   491:     sprBankShifted = false;
   492:     sprBankNumber = (0 << 8);
   493:     //768x512でスプライトを表示
   494:     spr768x512 = spr768x512Request;
   495:     sprAccessible = spr768x512;
   496:     //512x512でBG1を表示
   497:     spr512bg1 = spr512bg1Request;
   498:     if (SPR_RC_SCROLL_ON) {
   499:       //行スクロールと列スクロール
   500:       sprRcScrollOn = sprRcScrollRequest;
   501:       Arrays.fill (sprRowScroll, 0);
   502:       Arrays.fill (sprColScroll, 0);
   503:     }
   504: 
   505:     Arrays.fill (sprX, (short) 0);
   506:     Arrays.fill (sprY, (short) 0);
   507:     Arrays.fill (sprNum, (short) 0);
   508:     Arrays.fill (sprColPort, (short) 0);
   509:     Arrays.fill (sprPrw, (byte) 0);
   510:     Arrays.fill (sprH, false);
   511:     Arrays.fill (sprV, false);
   512:     Arrays.fill (sprF, 0);
   513:     Arrays.fill (sprRRmap, 0);
   514:     Arrays.fill (sprPatPort, 0);
   515:     Arrays.fill (sprPPmap, 0);
   516:     Arrays.fill (sprTNum, (short) 0);
   517:     Arrays.fill (sprTColPort, (short) 0);
   518:     Arrays.fill (sprTH, false);
   519:     Arrays.fill (sprTV, false);
   520:   }  //sprReset()
   521: 
   522: 
   523:   //
   524:   //  ノーマル
   525:   //    ラスタ(dst=-2,src=-2)
   526:   //      表(0)にスプライト(0)を並べる
   527:   //      表(0)と裏(-1)を入れ換える
   528:   //    ラスタ(dst=-1,src=-1)
   529:   //      表(-1)を表(1)として再利用する
   530:   //      表(1)にスプライト(1)を並べる
   531:   //      表(1)と裏(0)を入れ換える
   532:   //      表(0)にバックグラウンド(0)を並べる
   533:   //    ラスタ(dst=src)
   534:   //      表(dst)のスプライト(src)とバックグラウンド(src)を重ねる
   535:   //      表(dst)を描画する
   536:   //      表(dst)を表(dst+2)として再利用する
   537:   //      表(dst+2)にスプライト(src+2)を並べる
   538:   //      表(dst+2)と裏(dst+1)を入れ換える
   539:   //      表(dst+1)にバックグラウンド(src+1)を並べる
   540:   //
   541:   //  ラスタ2度読み
   542:   //    偶数ラスタ(dst=-2,src=-1)
   543:   //      表(0)にスプライト(0)を並べる
   544:   //      表(0)と裏(-1)を入れ換える
   545:   //    奇数ラスタ(dst=-1,src=-1)
   546:   //      表(-1)を表(1)として再利用する
   547:   //      表(1)にスプライト(0)を並べる
   548:   //      表(1)と裏(0)を入れ換える
   549:   //      表(0)にバックグラウンド(0)を並べる
   550:   //    偶数ラスタ(dst=src*2)
   551:   //      表(dst)のスプライト(src)とバックグラウンド(src)を重ねる
   552:   //      表(dst)を描画する
   553:   //      表(dst)を表(dst+2)として再利用する
   554:   //      表(dst+2)にスプライト(src+1)を並べる
   555:   //      表(dst+2)と裏(dst+1)を入れ換える
   556:   //      表(dst+1)にバックグラウンド(src)を並べる
   557:   //    奇数ラスタ(dst=src*2+1)
   558:   //      表(dst)のスプライト(src)とバックグラウンド(src)を重ねる
   559:   //      表(dst)を描画する
   560:   //      表(dst)を表(dst+2)として再利用する
   561:   //      表(dst+2)にスプライト(src+1)を並べる
   562:   //      表(dst+2)と裏(dst+1)を入れ換える
   563:   //      表(dst+1)にバックグラウンド(src+1)を並べる
   564:   //
   565:   //  インタレース
   566:   //    ラスタ(dst=-4,src=-4)
   567:   //      表(0)にスプライト(0)を並べる
   568:   //      表(0)と裏(-2)を入れ換える
   569:   //    ラスタ(dst=-2,src=-2)
   570:   //      表(-2)を表(2)として再利用する
   571:   //      表(2)にスプライト(2)を並べる
   572:   //      表(2)と裏(0)を入れ換える
   573:   //      表(0)にバックグラウンド(0)を並べる
   574:   //    ラスタ(dst=src)
   575:   //      表(dst)のスプライト(src)とバックグラウンド(src)を重ねる
   576:   //      表(dst)を描画する
   577:   //      表(dst)を表(dst+4)として再利用する
   578:   //      表(dst+4)にスプライト(src+4)を並べる
   579:   //      表(dst+4)と裏(dst+2)を入れ換える
   580:   //      表(dst+2)にバックグラウンド(src+2)を並べる
   581:   //
   582:   //  スリット
   583:   //    ラスタ(dst=-4,src=-2)
   584:   //      表(0)にスプライト(0)を並べる
   585:   //      表(0)と裏(-2)を入れ換える
   586:   //    ラスタ(dst=-2,src=-1)
   587:   //      表(-2)を表(2)として再利用する
   588:   //      表(2)にスプライト(1)を並べる
   589:   //      表(2)と裏(0)を入れ換える
   590:   //      表(0)にバックグラウンド(0)を並べる
   591:   //    ラスタ(dst=src*2)
   592:   //      表(dst)のスプライト(src)とバックグラウンド(src)を重ねる
   593:   //      表(dst)を描画する
   594:   //      表(dst)を表(dst+4)として再利用する
   595:   //      表(dst+4)にスプライト(src+2)を並べる
   596:   //      表(dst+4)と裏(dst+2)を入れ換える
   597:   //      表(dst+2)にバックグラウンド(src+1)を並べる
   598:   //
   599: 
   600:   //sprSwap ()
   601:   //  表と裏を入れ換える
   602:   //
   603:   //!!! if (SPR_THREE_STEPS)
   604:   public static void sprSwap () {
   605:     int[] t = sprBuffer;
   606:     sprBuffer = sprShadowBuffer;
   607:     sprShadowBuffer = t;
   608:   }  //sprSwap()
   609: 
   610:   //sprStep1 (src)
   611:   //  スプライトを並べる
   612:   //
   613:   //  sprBuffer[2112 + x]
   614:   //    4bitパレット
   615:   //             28  24  20  16  12   8   4   0
   616:   //    手前← |---|SP3|BG0|SP2|BG1|SP1|---|---| →奥
   617:   //
   618:   //  sprBuffer[1056 + x]
   619:   //    パレットブロック
   620:   //             28  24  20  16  12   8   4   0
   621:   //    手前← |---|SP3|BG0|SP2|BG1|SP1|---|---| →奥
   622:   //
   623:   //!!! if (SPR_THREE_STEPS)
   624:   public static void sprStep1 (int src) {
   625:     //バッファをクリアする
   626:     //  4bitパレットとパレットブロックの両方をクリアすること
   627:     Arrays.fill (sprBuffer, 0);
   628:     //垂直映像開始位置の指定に伴う補正
   629:     src += sprReg7VBackEndCurr - CRTC.crtR06VBackEndCurr;
   630:     if (src < 0 || 1023 < src) {
   631:       return;
   632:     }
   633:     //水平映像開始位置の指定に伴う補正
   634:     int hStart = (sprReg6HBackEndCurr - CRTC.crtR02HBackEndCurr - 4) << 3;
   635:     int width16 = 16 + XEiJ.pnlScreenWidth;
   636:     //ラスタにかかっているスプライトの数
   637:     int cnt = sprSpritesPerRaster;  //1ラスタあたりのスプライト数-ラスタにかかっているスプライトの数
   638:     if (cnt == 0) {
   639:       return;
   640:     }
   641:     for (int i = (16 + src) << (SPR_SHIFT - 5), nn = 0; nn < sprNumberOfSprites; nn += 32) {
   642:       for (int map = sprRRmap[i++], n = nn; map != 0; map <<= 1, n++) {  //nは昇順
   643:         if (0 <= map) {  //このスプライトはラスタにかかっていない
   644:           continue;
   645:         }
   646:         int x = hStart + sprX[n];  //X座標。画面左端は16
   647:         if (x <= 0 || width16 <= x) {  //画面外
   648:           //画面外のスプライトは水平表示限界に影響する。X68030実機で確認
   649:           if (--cnt == 0) {  //今回のスプライトで終わりにする
   650:             return;
   651:           }
   652:           continue;
   653:         }
   654:         //  8x8のパターンを
   655:         //    +---+---+
   656:         //    | 0 | 2 |
   657:         //    +---+---+
   658:         //    | 1 | 3 |
   659:         //    +---+---+
   660:         //  の順序で並べる
   661:         int a = (sprNum[n] << 5) + (sprV[n] ? sprY[n] - src - 1 : 16 + src - sprY[n]);
   662:         int prw = sprPrw[n] << 3;  //プライオリティ*8。表示されていることがわかっているのでプライオリティは1~3のいずれかであるはず
   663:         int col = sprColCurr[n] << prw >>> 4;  //パレットブロック
   664:         int f = sprF[n];  //XPC1/PCS1
   665:         int s, t;
   666:         if ((t = f | sprPatCurr[a]) != 0) {  //左半分のパターンあり
   667:           if (sprH[n]) {  //左右反転あり。左半分→右半分
   668:             if ((s = 15       & t) != 0 && sprBuffer[2112 +  8 + x] >>> prw == 0) {  //ドットがありかつ若い番号のスプライトよりも優先順位が高い
   669:               sprBuffer[2112 +  8 + x] = s        << prw;
   670:               sprBuffer[1056 +  8 + x] = col;
   671:             }
   672:             if ((s = 15 <<  4 & t) != 0 && sprBuffer[2112 +  9 + x] >>> prw == 0) {  //ドットがありかつ若い番号のスプライトよりも優先順位が高い
   673:               sprBuffer[2112 +  9 + x] = s >>>  4 << prw;
   674:               sprBuffer[1056 +  9 + x] = col;
   675:             }
   676:             if ((s = 15 <<  8 & t) != 0 && sprBuffer[2112 + 10 + x] >>> prw == 0) {  //ドットがありかつ若い番号のスプライトよりも優先順位が高い
   677:               sprBuffer[2112 + 10 + x] = s >>>  8 << prw;
   678:               sprBuffer[1056 + 10 + x] = col;
   679:             }
   680:             if ((s = 15 << 12 & t) != 0 && sprBuffer[2112 + 11 + x] >>> prw == 0) {  //ドットがありかつ若い番号のスプライトよりも優先順位が高い
   681:               sprBuffer[2112 + 11 + x] = s >>> 12 << prw;
   682:               sprBuffer[1056 + 11 + x] = col;
   683:             }
   684:             if ((s = 15 << 16 & t) != 0 && sprBuffer[2112 + 12 + x] >>> prw == 0) {  //ドットがありかつ若い番号のスプライトよりも優先順位が高い
   685:               sprBuffer[2112 + 12 + x] = s >>> 16 << prw;
   686:               sprBuffer[1056 + 12 + x] = col;
   687:             }
   688:             if ((s = 15 << 20 & t) != 0 && sprBuffer[2112 + 13 + x] >>> prw == 0) {  //ドットがありかつ若い番号のスプライトよりも優先順位が高い
   689:               sprBuffer[2112 + 13 + x] = s >>> 20 << prw;
   690:               sprBuffer[1056 + 13 + x] = col;
   691:             }
   692:             if ((s = 15 << 24 & t) != 0 && sprBuffer[2112 + 14 + x] >>> prw == 0) {  //ドットがありかつ若い番号のスプライトよりも優先順位が高い
   693:               sprBuffer[2112 + 14 + x] = s >>> 24 << prw;
   694:               sprBuffer[1056 + 14 + x] = col;
   695:             }
   696:             if ((s = t >>> 28    ) != 0 && sprBuffer[2112 + 15 + x] >>> prw == 0) {  //ドットがありかつ若い番号のスプライトよりも優先順位が高い
   697:               sprBuffer[2112 + 15 + x] = s        << prw;
   698:               sprBuffer[1056 + 15 + x] = col;
   699:             }
   700:           } else {  //左右反転なし。左半分→左半分
   701:             if ((s = t >>> 28    ) != 0 && sprBuffer[2112 +      x] >>> prw == 0) {  //ドットがありかつ若い番号のスプライトよりも優先順位が高い
   702:               sprBuffer[2112 +      x] = s        << prw;
   703:               sprBuffer[1056 +      x] = col;
   704:             }
   705:             if ((s = 15 << 24 & t) != 0 && sprBuffer[2112 +  1 + x] >>> prw == 0) {  //ドットがありかつ若い番号のスプライトよりも優先順位が高い
   706:               sprBuffer[2112 +  1 + x] = s >>> 24 << prw;
   707:               sprBuffer[1056 +  1 + x] = col;
   708:             }
   709:             if ((s = 15 << 20 & t) != 0 && sprBuffer[2112 +  2 + x] >>> prw == 0) {  //ドットがありかつ若い番号のスプライトよりも優先順位が高い
   710:               sprBuffer[2112 +  2 + x] = s >>> 20 << prw;
   711:               sprBuffer[1056 +  2 + x] = col;
   712:             }
   713:             if ((s = 15 << 16 & t) != 0 && sprBuffer[2112 +  3 + x] >>> prw == 0) {  //ドットがありかつ若い番号のスプライトよりも優先順位が高い
   714:               sprBuffer[2112 +  3 + x] = s >>> 16 << prw;
   715:               sprBuffer[1056 +  3 + x] = col;
   716:             }
   717:             if ((s = 15 << 12 & t) != 0 && sprBuffer[2112 +  4 + x] >>> prw == 0) {  //ドットがありかつ若い番号のスプライトよりも優先順位が高い
   718:               sprBuffer[2112 +  4 + x] = s >>> 12 << prw;
   719:               sprBuffer[1056 +  4 + x] = col;
   720:             }
   721:             if ((s = 15 <<  8 & t) != 0 && sprBuffer[2112 +  5 + x] >>> prw == 0) {  //ドットがありかつ若い番号のスプライトよりも優先順位が高い
   722:               sprBuffer[2112 +  5 + x] = s >>>  8 << prw;
   723:               sprBuffer[1056 +  5 + x] = col;
   724:             }
   725:             if ((s = 15 <<  4 & t) != 0 && sprBuffer[2112 +  6 + x] >>> prw == 0) {  //ドットがありかつ若い番号のスプライトよりも優先順位が高い
   726:               sprBuffer[2112 +  6 + x] = s >>>  4 << prw;
   727:               sprBuffer[1056 +  6 + x] = col;
   728:             }
   729:             if ((s = 15       & t) != 0 && sprBuffer[2112 +  7 + x] >>> prw == 0) {  //ドットがありかつ若い番号のスプライトよりも優先順位が高い
   730:               sprBuffer[2112 +  7 + x] = s        << prw;
   731:               sprBuffer[1056 +  7 + x] = col;
   732:             }
   733:           }  //if 左右反転あり/左右反転なし
   734:         }  //if 左半分のパターンあり
   735:         if ((t = f | sprPatCurr[16 + a]) != 0) {  //右半分のパターンあり
   736:           if (sprH[n]) {  //左右反転あり。右半分→左半分
   737:             if ((s = 15       & t) != 0 && sprBuffer[2112 +      x] >>> prw == 0) {  //ドットがありかつ若い番号のスプライトよりも優先順位が高い
   738:               sprBuffer[2112 +      x] = s        << prw;
   739:               sprBuffer[1056 +      x] = col;
   740:             }
   741:             if ((s = 15 <<  4 & t) != 0 && sprBuffer[2112 +  1 + x] >>> prw == 0) {  //ドットがありかつ若い番号のスプライトよりも優先順位が高い
   742:               sprBuffer[2112 +  1 + x] = s >>>  4 << prw;
   743:               sprBuffer[1056 +  1 + x] = col;
   744:             }
   745:             if ((s = 15 <<  8 & t) != 0 && sprBuffer[2112 +  2 + x] >>> prw == 0) {  //ドットがありかつ若い番号のスプライトよりも優先順位が高い
   746:               sprBuffer[2112 +  2 + x] = s >>>  8 << prw;
   747:               sprBuffer[1056 +  2 + x] = col;
   748:             }
   749:             if ((s = 15 << 12 & t) != 0 && sprBuffer[2112 +  3 + x] >>> prw == 0) {  //ドットがありかつ若い番号のスプライトよりも優先順位が高い
   750:               sprBuffer[2112 +  3 + x] = s >>> 12 << prw;
   751:               sprBuffer[1056 +  3 + x] = col;
   752:             }
   753:             if ((s = 15 << 16 & t) != 0 && sprBuffer[2112 +  4 + x] >>> prw == 0) {  //ドットがありかつ若い番号のスプライトよりも優先順位が高い
   754:               sprBuffer[2112 +  4 + x] = s >>> 16 << prw;
   755:               sprBuffer[1056 +  4 + x] = col;
   756:             }
   757:             if ((s = 15 << 20 & t) != 0 && sprBuffer[2112 +  5 + x] >>> prw == 0) {  //ドットがありかつ若い番号のスプライトよりも優先順位が高い
   758:               sprBuffer[2112 +  5 + x] = s >>> 20 << prw;
   759:               sprBuffer[1056 +  5 + x] = col;
   760:             }
   761:             if ((s = 15 << 24 & t) != 0 && sprBuffer[2112 +  6 + x] >>> prw == 0) {  //ドットがありかつ若い番号のスプライトよりも優先順位が高い
   762:               sprBuffer[2112 +  6 + x] = s >>> 24 << prw;
   763:               sprBuffer[1056 +  6 + x] = col;
   764:             }
   765:             if ((s = t >>> 28    ) != 0 && sprBuffer[2112 +  7 + x] >>> prw == 0) {  //ドットがありかつ若い番号のスプライトよりも優先順位が高い
   766:               sprBuffer[2112 +  7 + x] = s        << prw;
   767:               sprBuffer[1056 +  7 + x] = col;
   768:             }
   769:           } else {  //左右反転なし。右半分→右半分
   770:             if ((s = t >>> 28    ) != 0 && sprBuffer[2112 +  8 + x] >>> prw == 0) {  //ドットがありかつ若い番号のスプライトよりも優先順位が高い
   771:               sprBuffer[2112 +  8 + x] = s        << prw;
   772:               sprBuffer[1056 +  8 + x] = col;
   773:             }
   774:             if ((s = 15 << 24 & t) != 0 && sprBuffer[2112 +  9 + x] >>> prw == 0) {  //ドットがありかつ若い番号のスプライトよりも優先順位が高い
   775:               sprBuffer[2112 +  9 + x] = s >>> 24 << prw;
   776:               sprBuffer[1056 +  9 + x] = col;
   777:             }
   778:             if ((s = 15 << 20 & t) != 0 && sprBuffer[2112 + 10 + x] >>> prw == 0) {  //ドットがありかつ若い番号のスプライトよりも優先順位が高い
   779:               sprBuffer[2112 + 10 + x] = s >>> 20 << prw;
   780:               sprBuffer[1056 + 10 + x] = col;
   781:             }
   782:             if ((s = 15 << 16 & t) != 0 && sprBuffer[2112 + 11 + x] >>> prw == 0) {  //ドットがありかつ若い番号のスプライトよりも優先順位が高い
   783:               sprBuffer[2112 + 11 + x] = s >>> 16 << prw;
   784:               sprBuffer[1056 + 11 + x] = col;
   785:             }
   786:             if ((s = 15 << 12 & t) != 0 && sprBuffer[2112 + 12 + x] >>> prw == 0) {  //ドットがありかつ若い番号のスプライトよりも優先順位が高い
   787:               sprBuffer[2112 + 12 + x] = s >>> 12 << prw;
   788:               sprBuffer[1056 + 12 + x] = col;
   789:             }
   790:             if ((s = 15 <<  8 & t) != 0 && sprBuffer[2112 + 13 + x] >>> prw == 0) {  //ドットがありかつ若い番号のスプライトよりも優先順位が高い
   791:               sprBuffer[2112 + 13 + x] = s >>>  8 << prw;
   792:               sprBuffer[1056 + 13 + x] = col;
   793:             }
   794:             if ((s = 15 <<  4 & t) != 0 && sprBuffer[2112 + 14 + x] >>> prw == 0) {  //ドットがありかつ若い番号のスプライトよりも優先順位が高い
   795:               sprBuffer[2112 + 14 + x] = s >>>  4 << prw;
   796:               sprBuffer[1056 + 14 + x] = col;
   797:             }
   798:             if ((s = 15       & t) != 0 && sprBuffer[2112 + 15 + x] >>> prw == 0) {  //ドットがありかつ若い番号のスプライトよりも優先順位が高い
   799:               sprBuffer[2112 + 15 + x] = s        << prw;
   800:               sprBuffer[1056 + 15 + x] = col;
   801:             }
   802:           }  //if 左右反転あり/左右反転なし
   803:         }  //if 右半分のパターンあり
   804:         if (--cnt == 0) {  //今回のスプライトで終わりにする
   805:           return;
   806:         }
   807:       }  //for map,n
   808:     }  // for i,nn
   809:   }  //sprStep1(int)
   810: 
   811:   //sprStep2 (src)
   812:   //  バックグラウンドを並べる
   813:   //
   814:   //  sprBuffer[2112 + x]
   815:   //    4bitパレット
   816:   //             28  24  20  16  12   8   4   0
   817:   //    手前← |---|SP3|BG0|SP2|BG1|SP1|---|---| →奥
   818:   //
   819:   //  sprBuffer[1056 + x]
   820:   //    パレットブロック
   821:   //             28  24  20  16  12   8   4   0
   822:   //    手前← |---|SP3|BG0|SP2|BG1|SP1|---|---| →奥
   823:   //
   824:   //!!! if (SPR_THREE_STEPS)
   825:   public static void sprStep2 (int src) {
   826:     //垂直映像開始位置の指定に伴う補正
   827:     src += sprReg7VBackEndCurr - CRTC.crtR06VBackEndCurr;
   828:     if (src < 0 || 1023 < src) {
   829:       return;
   830:     }
   831:     //水平映像開始位置の指定に伴う補正
   832:     int hStart = (sprReg6HBackEndCurr - CRTC.crtR02HBackEndCurr - 4) << 3;
   833:     int width16 = 16 + XEiJ.pnlScreenWidth;
   834:     if ((sprReg8ResoCurr & 3) == 0) {  //水平256ドット、BGパターンは8x8、BG仮想画面は512x512、BG0とBG1
   835:       final short[] tnum = sprTNum, tcol = sprTColCurr;
   836:       final boolean[] th = sprTH, tv = sprTV;
   837:       int x, y = 0, sx, sy = 0, y0 = 0;
   838:       //BG0
   839:       //  BG0の有無は表示ラスタまで分からないので1ラスタ手前では常に展開しておかなければならない
   840:       int ofst = (sprReg4BgCtrlCurr << (12 - 1)) & (3 << 12);  //4096*(BG0に割り当てられているテキスト)
   841:       if (SPR_RC_SCROLL_ON && sprRcScrollOn) {
   842:         y0 = (src + sprReg1Bg0YCurr) & 511;
   843:         x = 16 + hStart - sprReg0Bg0XCurr - sprRowScroll[y0 >> 3];  //X座標。画面左端は16
   844:         sx = (((x & 7) - x) >> 3) & 63;  //テキストX座標
   845:         x &= 7;
   846:       } else {
   847:         x = 16 + hStart - sprReg0Bg0XCurr;  //X座標。画面左端は16
   848:         y = (src + sprReg1Bg0YCurr) & 511;
   849:         sx = (((x & 7) - x) >> 3) & 63;  //テキストX座標
   850:         sy = ofst + ((y >> 3) << 6);  //ofst+(テキストY座標*64)
   851:         x &= 7;
   852:         y &= 7;
   853:       }
   854:       while (x < width16) {
   855:         if (SPR_RC_SCROLL_ON && sprRcScrollOn) {
   856:           y = (y0 + sprColScroll[sx]) & 511;
   857:           sy = ofst + ((y >> 3) << 6);  //ofst+(テキストY座標*64)
   858:           y &= 7;
   859:         }
   860:         int t;
   861:         if ((t = sprPatCurr[tnum[sy + sx] + (tv[sy + sx] ? 7 - y : y)]) != 0) {  //パターンあり
   862:           if (th[sy + sx]) {  //左右反転あり
   863:             sprBuffer[2112 +      x] |= (t        & 15) << 20;
   864:             sprBuffer[2112 +  1 + x] |= (t >>>  4 & 15) << 20;
   865:             sprBuffer[2112 +  2 + x] |= (t >>>  8 & 15) << 20;
   866:             sprBuffer[2112 +  3 + x] |= (t >>> 12 & 15) << 20;
   867:             sprBuffer[2112 +  4 + x] |= (t >>> 16 & 15) << 20;
   868:             sprBuffer[2112 +  5 + x] |= (t >>> 20 & 15) << 20;
   869:             sprBuffer[2112 +  6 + x] |= (t >>> 24 & 15) << 20;
   870:             sprBuffer[2112 +  7 + x] |= (t >>> 28     ) << 20;
   871:           } else {  //左右反転なし
   872:             sprBuffer[2112 +      x] |= (t >>> 28     ) << 20;
   873:             sprBuffer[2112 +  1 + x] |= (t >>> 24 & 15) << 20;
   874:             sprBuffer[2112 +  2 + x] |= (t >>> 20 & 15) << 20;
   875:             sprBuffer[2112 +  3 + x] |= (t >>> 16 & 15) << 20;
   876:             sprBuffer[2112 +  4 + x] |= (t >>> 12 & 15) << 20;
   877:             sprBuffer[2112 +  5 + x] |= (t >>>  8 & 15) << 20;
   878:             sprBuffer[2112 +  6 + x] |= (t >>>  4 & 15) << 20;
   879:             sprBuffer[2112 +  7 + x] |= (t        & 15) << 20;
   880:           }  //if 左右反転あり/左右反転なし
   881:         }  //if パターンあり
   882:         if ((t = tcol[sy + sx]) != 0) {  //パレットブロックが0でないとき。バックグラウンドは4bitパレットが0でもパレットブロックが必要
   883:           t <<= 20 - 4;  //tcolはパレットブロック<<4。ここでは4bitパレットと同じ位置に置く
   884:           sprBuffer[1056      + x] |= t;
   885:           sprBuffer[1056 +  1 + x] |= t;
   886:           sprBuffer[1056 +  2 + x] |= t;
   887:           sprBuffer[1056 +  3 + x] |= t;
   888:           sprBuffer[1056 +  4 + x] |= t;
   889:           sprBuffer[1056 +  5 + x] |= t;
   890:           sprBuffer[1056 +  6 + x] |= t;
   891:           sprBuffer[1056 +  7 + x] |= t;
   892:         }
   893:         x += 8;
   894:         sx = (sx + 1) & 63;
   895:       }  //while x<width16
   896:       //BG1
   897:       //  BG1の有無は表示ラスタまで分からないので1ラスタ手前では常に展開しておかなければならない
   898:       ofst = (sprReg4BgCtrlCurr << (12 - 4)) & (3 << 12);  //4096*(BG1に割り当てられているテキスト)
   899:       if (SPR_RC_SCROLL_ON && sprRcScrollOn) {
   900:         y0 = (src + sprReg3Bg1YCurr) & 511;
   901:         x = 16 + hStart - sprReg2Bg1XCurr - sprRowScroll[64 * 1 + (y0 >> 3)];  //X座標。画面左端は16
   902:         sx = (((x & 7) - x) >> 3) & 63;  //テキストX座標
   903:         x &= 7;
   904:       } else {
   905:         x = 16 + hStart - sprReg2Bg1XCurr;  //X座標。画面左端は16
   906:         y = (src + sprReg3Bg1YCurr) & 511;
   907:         sx = (((x & 7) - x) >> 3) & 63;  //テキストX座標
   908:         sy = ofst + ((y >> 3) << 6);  //ofst+(テキストY座標*64)
   909:         x &= 7;
   910:         y &= 7;
   911:       }
   912:       while (x < width16) {
   913:         if (SPR_RC_SCROLL_ON && sprRcScrollOn) {
   914:           y = (y0 + sprColScroll[64 * 1 + sx]) & 511;
   915:           sy = ofst + ((y >> 3) << 6);  //ofst+(テキストY座標*64)
   916:           y &= 7;
   917:         }
   918:         int t;
   919:         if ((t = sprPatCurr[tnum[sy + sx] + (tv[sy + sx] ? 7 - y : y)]) != 0) {  //パターンあり
   920:           if (th[sy + sx]) {  //左右反転あり
   921:             sprBuffer[2112 +      x] |= (t        & 15) << 12;
   922:             sprBuffer[2112 +  1 + x] |= (t >>>  4 & 15) << 12;
   923:             sprBuffer[2112 +  2 + x] |= (t >>>  8 & 15) << 12;
   924:             sprBuffer[2112 +  3 + x] |= (t >>> 12 & 15) << 12;
   925:             sprBuffer[2112 +  4 + x] |= (t >>> 16 & 15) << 12;
   926:             sprBuffer[2112 +  5 + x] |= (t >>> 20 & 15) << 12;
   927:             sprBuffer[2112 +  6 + x] |= (t >>> 24 & 15) << 12;
   928:             sprBuffer[2112 +  7 + x] |= (t >>> 28     ) << 12;
   929:           } else {  //左右反転なし
   930:             sprBuffer[2112 +      x] |= (t >>> 28     ) << 12;
   931:             sprBuffer[2112 +  1 + x] |= (t >>> 24 & 15) << 12;
   932:             sprBuffer[2112 +  2 + x] |= (t >>> 20 & 15) << 12;
   933:             sprBuffer[2112 +  3 + x] |= (t >>> 16 & 15) << 12;
   934:             sprBuffer[2112 +  4 + x] |= (t >>> 12 & 15) << 12;
   935:             sprBuffer[2112 +  5 + x] |= (t >>>  8 & 15) << 12;
   936:             sprBuffer[2112 +  6 + x] |= (t >>>  4 & 15) << 12;
   937:             sprBuffer[2112 +  7 + x] |= (t        & 15) << 12;
   938:           }  //if 左右反転あり/左右反転なし
   939:         }  //if パターンあり
   940:         if ((t = tcol[sy + sx]) != 0) {  //パレットブロックが0でないとき。バックグラウンドは4bitパレットが0でもパレットブロックが必要
   941:           t <<= 12 - 4;  //tcolはパレットブロック<<4。ここでは4bitパレットと同じ位置に置く
   942:           sprBuffer[1056      + x] |= t;
   943:           sprBuffer[1056 +  1 + x] |= t;
   944:           sprBuffer[1056 +  2 + x] |= t;
   945:           sprBuffer[1056 +  3 + x] |= t;
   946:           sprBuffer[1056 +  4 + x] |= t;
   947:           sprBuffer[1056 +  5 + x] |= t;
   948:           sprBuffer[1056 +  6 + x] |= t;
   949:           sprBuffer[1056 +  7 + x] |= t;
   950:         }
   951:         x += 8;
   952:         sx = (sx + 1) & 63;
   953:       }  //while x<width16
   954:     } else {  //水平512ドット、BGパターンは16x16、BG仮想画面は1024x1024、BG0のみ
   955:       final short[] tnum = sprTNum, tcol = sprTColCurr;
   956:       final boolean[] th = sprTH, tv = sprTV;
   957:       int x, y = 0, sx, sy = 0, y0 = 0;
   958:       //BG0
   959:       //  BG0の有無は表示ラスタまで分からないので1ラスタ手前では常に展開しておかなければならない
   960:       int ofst = (sprReg4BgCtrlCurr << (12 - 1)) & (3 << 12);  //4096*(BG0に割り当てられているテキスト)
   961:       if (SPR_RC_SCROLL_ON && sprRcScrollOn) {
   962:         y0 = (src + sprReg1Bg0YCurr) & 1023;
   963:         x = 16 + hStart - sprReg0Bg0XCurr - sprRowScroll[y0 >> 4];  //X座標。画面左端は16
   964:         sx = (((x & 15) - x) >> 4) & 63;  //テキストX座標
   965:         x &= 15;
   966:       } else {
   967:         x = 16 + hStart - sprReg0Bg0XCurr;  //X座標。画面左端は16
   968:         y = (src + sprReg1Bg0YCurr) & 1023;
   969:         sx = (((x & 15) - x) >> 4) & 63;  //テキストX座標
   970:         sy = ofst + ((y >> 4) << 6);  //ofst+(テキストY座標*64)
   971:         x &= 15;
   972:         y &= 15;
   973:       }
   974:       while (x < width16) {
   975:         if (SPR_RC_SCROLL_ON && sprRcScrollOn) {
   976:           y = (y0 + sprColScroll[sx]) & 1023;
   977:           sy = ofst + ((y >> 4) << 6);  //ofst+(テキストY座標*64)
   978:           y &= 15;
   979:         }
   980:         int a = (tnum[sy + sx] << 2) + (tv[sy + sx] ? 15 - y : y);
   981:         int t;
   982:         if ((t = sprPatCurr[a]) != 0) {  //左半分のパターンあり
   983:           if (th[sy + sx]) {  //左右反転あり。左半分→右半分
   984:             sprBuffer[2112 +  8 + x] |= (t        & 15) << 20;
   985:             sprBuffer[2112 +  9 + x] |= (t >>>  4 & 15) << 20;
   986:             sprBuffer[2112 + 10 + x] |= (t >>>  8 & 15) << 20;
   987:             sprBuffer[2112 + 11 + x] |= (t >>> 12 & 15) << 20;
   988:             sprBuffer[2112 + 12 + x] |= (t >>> 16 & 15) << 20;
   989:             sprBuffer[2112 + 13 + x] |= (t >>> 20 & 15) << 20;
   990:             sprBuffer[2112 + 14 + x] |= (t >>> 24 & 15) << 20;
   991:             sprBuffer[2112 + 15 + x] |= (t >>> 28     ) << 20;
   992:           } else {  //左右反転なし。左半分→左半分
   993:             sprBuffer[2112 +      x] |= (t >>> 28     ) << 20;
   994:             sprBuffer[2112 +  1 + x] |= (t >>> 24 & 15) << 20;
   995:             sprBuffer[2112 +  2 + x] |= (t >>> 20 & 15) << 20;
   996:             sprBuffer[2112 +  3 + x] |= (t >>> 16 & 15) << 20;
   997:             sprBuffer[2112 +  4 + x] |= (t >>> 12 & 15) << 20;
   998:             sprBuffer[2112 +  5 + x] |= (t >>>  8 & 15) << 20;
   999:             sprBuffer[2112 +  6 + x] |= (t >>>  4 & 15) << 20;
  1000:             sprBuffer[2112 +  7 + x] |= (t        & 15) << 20;
  1001:           }  //if 左右反転あり/左右反転なし
  1002:         }  //if 左半分のパターンあり
  1003:         if ((t = sprPatCurr[16 + a]) != 0) {  //右半分のパターンあり
  1004:           if (th[sy + sx]) {  //左右反転あり。右半分→左半分
  1005:             sprBuffer[2112 +      x] |= (t        & 15) << 20;
  1006:             sprBuffer[2112 +  1 + x] |= (t >>>  4 & 15) << 20;
  1007:             sprBuffer[2112 +  2 + x] |= (t >>>  8 & 15) << 20;
  1008:             sprBuffer[2112 +  3 + x] |= (t >>> 12 & 15) << 20;
  1009:             sprBuffer[2112 +  4 + x] |= (t >>> 16 & 15) << 20;
  1010:             sprBuffer[2112 +  5 + x] |= (t >>> 20 & 15) << 20;
  1011:             sprBuffer[2112 +  6 + x] |= (t >>> 24 & 15) << 20;
  1012:             sprBuffer[2112 +  7 + x] |= (t >>> 28     ) << 20;
  1013:           } else {  //左右反転なし。右半分→右半分
  1014:             sprBuffer[2112 +  8 + x] |= (t >>> 28     ) << 20;
  1015:             sprBuffer[2112 +  9 + x] |= (t >>> 24 & 15) << 20;
  1016:             sprBuffer[2112 + 10 + x] |= (t >>> 20 & 15) << 20;
  1017:             sprBuffer[2112 + 11 + x] |= (t >>> 16 & 15) << 20;
  1018:             sprBuffer[2112 + 12 + x] |= (t >>> 12 & 15) << 20;
  1019:             sprBuffer[2112 + 13 + x] |= (t >>>  8 & 15) << 20;
  1020:             sprBuffer[2112 + 14 + x] |= (t >>>  4 & 15) << 20;
  1021:             sprBuffer[2112 + 15 + x] |= (t        & 15) << 20;
  1022:           }  //if 左右反転あり/左右反転なし
  1023:         }  //if 右半分のパターンあり
  1024:         if ((t = tcol[sy + sx]) != 0) {  //パレットブロックが0でないとき。バックグラウンドは4bitパレットが0でもパレットブロックが必要
  1025:           t <<= 20 - 4;  //tcolはパレットブロック<<4。ここでは4bitパレットと同じ位置に置く
  1026:           sprBuffer[1056      + x] |= t;
  1027:           sprBuffer[1056 +  1 + x] |= t;
  1028:           sprBuffer[1056 +  2 + x] |= t;
  1029:           sprBuffer[1056 +  3 + x] |= t;
  1030:           sprBuffer[1056 +  4 + x] |= t;
  1031:           sprBuffer[1056 +  5 + x] |= t;
  1032:           sprBuffer[1056 +  6 + x] |= t;
  1033:           sprBuffer[1056 +  7 + x] |= t;
  1034:           sprBuffer[1056 +  8 + x] |= t;
  1035:           sprBuffer[1056 +  9 + x] |= t;
  1036:           sprBuffer[1056 + 10 + x] |= t;
  1037:           sprBuffer[1056 + 11 + x] |= t;
  1038:           sprBuffer[1056 + 12 + x] |= t;
  1039:           sprBuffer[1056 + 13 + x] |= t;
  1040:           sprBuffer[1056 + 14 + x] |= t;
  1041:           sprBuffer[1056 + 15 + x] |= t;
  1042:         }  //if パレットブロックが0でないとき
  1043:         x += 16;
  1044:         sx = (sx + 1) & 63;
  1045:       }  //while x<width16
  1046:       if (spr512bg1) {  //512x512でBG1を表示
  1047:         //BG1
  1048:         //  BG1の有無は表示ラスタまで分からないので1ラスタ手前では常に展開しておかなければならない
  1049:         ofst = (sprReg4BgCtrlCurr << (12 - 4)) & (3 << 12);  //4096*(BG1に割り当てられているテキスト)
  1050:         if (SPR_RC_SCROLL_ON && sprRcScrollOn) {
  1051:           y0 = (src + sprReg3Bg1YCurr) & 1023;
  1052:           x = 16 + hStart - sprReg2Bg1XCurr - sprRowScroll[64 * 1 + (y0 >> 4)];  //X座標。画面左端は16
  1053:           sx = (((x & 15) - x) >> 4) & 63;  //テキストX座標
  1054:           x &= 15;
  1055:         } else {
  1056:           x = 16 + hStart - sprReg2Bg1XCurr;  //X座標。画面左端は16
  1057:           y = (src + sprReg3Bg1YCurr) & 1023;
  1058:           sx = (((x & 15) - x) >> 4) & 63;  //テキストX座標
  1059:           sy = ofst + ((y >> 4) << 6);  //ofst+(テキストY座標*64)
  1060:           x &= 15;
  1061:           y &= 15;
  1062:         }
  1063:         while (x < width16) {
  1064:           if (SPR_RC_SCROLL_ON && sprRcScrollOn) {
  1065:             y = (y0 + sprColScroll[64 * 1 + sx]) & 1023;
  1066:             sy = ofst + ((y >> 4) << 6);  //ofst+(テキストY座標*64)
  1067:             y &= 15;
  1068:           }
  1069:           int a = (tnum[sy + sx] << 2) + (tv[sy + sx] ? 15 - y : y);
  1070:           int t;
  1071:           if ((t = sprPatCurr[a]) != 0) {  //左半分のパターンあり
  1072:             if (th[sy + sx]) {  //左右反転あり。左半分→右半分
  1073:               sprBuffer[2112 +  8 + x] |= (t        & 15) << 12;
  1074:               sprBuffer[2112 +  9 + x] |= (t >>>  4 & 15) << 12;
  1075:               sprBuffer[2112 + 10 + x] |= (t >>>  8 & 15) << 12;
  1076:               sprBuffer[2112 + 11 + x] |= (t >>> 12 & 15) << 12;
  1077:               sprBuffer[2112 + 12 + x] |= (t >>> 16 & 15) << 12;
  1078:               sprBuffer[2112 + 13 + x] |= (t >>> 20 & 15) << 12;
  1079:               sprBuffer[2112 + 14 + x] |= (t >>> 24 & 15) << 12;
  1080:               sprBuffer[2112 + 15 + x] |= (t >>> 28     ) << 12;
  1081:             } else {  //左右反転なし。左半分→左半分
  1082:               sprBuffer[2112 +      x] |= (t >>> 28     ) << 12;
  1083:               sprBuffer[2112 +  1 + x] |= (t >>> 24 & 15) << 12;
  1084:               sprBuffer[2112 +  2 + x] |= (t >>> 20 & 15) << 12;
  1085:               sprBuffer[2112 +  3 + x] |= (t >>> 16 & 15) << 12;
  1086:               sprBuffer[2112 +  4 + x] |= (t >>> 12 & 15) << 12;
  1087:               sprBuffer[2112 +  5 + x] |= (t >>>  8 & 15) << 12;
  1088:               sprBuffer[2112 +  6 + x] |= (t >>>  4 & 15) << 12;
  1089:               sprBuffer[2112 +  7 + x] |= (t        & 15) << 12;
  1090:             }  //if 左右反転あり/左右反転なし
  1091:           }  //if 左半分のパターンあり
  1092:           if ((t = sprPatCurr[16 + a]) != 0) {  //右半分のパターンあり
  1093:             if (th[sy + sx]) {  //左右反転あり。右半分→左半分
  1094:               sprBuffer[2112 +      x] |= (t        & 15) << 12;
  1095:               sprBuffer[2112 +  1 + x] |= (t >>>  4 & 15) << 12;
  1096:               sprBuffer[2112 +  2 + x] |= (t >>>  8 & 15) << 12;
  1097:               sprBuffer[2112 +  3 + x] |= (t >>> 12 & 15) << 12;
  1098:               sprBuffer[2112 +  4 + x] |= (t >>> 16 & 15) << 12;
  1099:               sprBuffer[2112 +  5 + x] |= (t >>> 20 & 15) << 12;
  1100:               sprBuffer[2112 +  6 + x] |= (t >>> 24 & 15) << 12;
  1101:               sprBuffer[2112 +  7 + x] |= (t >>> 28     ) << 12;
  1102:             } else {  //左右反転なし。右半分→右半分
  1103:               sprBuffer[2112 +  8 + x] |= (t >>> 28     ) << 12;
  1104:               sprBuffer[2112 +  9 + x] |= (t >>> 24 & 15) << 12;
  1105:               sprBuffer[2112 + 10 + x] |= (t >>> 20 & 15) << 12;
  1106:               sprBuffer[2112 + 11 + x] |= (t >>> 16 & 15) << 12;
  1107:               sprBuffer[2112 + 12 + x] |= (t >>> 12 & 15) << 12;
  1108:               sprBuffer[2112 + 13 + x] |= (t >>>  8 & 15) << 12;
  1109:               sprBuffer[2112 + 14 + x] |= (t >>>  4 & 15) << 12;
  1110:               sprBuffer[2112 + 15 + x] |= (t        & 15) << 12;
  1111:             }  //if 左右反転あり/左右反転なし
  1112:           }  //if 右半分のパターンあり
  1113:           if ((t = tcol[sy + sx]) != 0) {  //パレットブロックが0でないとき。バックグラウンドは4bitパレットが0でもパレットブロックが必要
  1114:             t <<= 12 - 4;  //tcolはパレットブロック<<4。ここでは4bitパレットと同じ位置に置く
  1115:             sprBuffer[1056      + x] |= t;
  1116:             sprBuffer[1056 +  1 + x] |= t;
  1117:             sprBuffer[1056 +  2 + x] |= t;
  1118:             sprBuffer[1056 +  3 + x] |= t;
  1119:             sprBuffer[1056 +  4 + x] |= t;
  1120:             sprBuffer[1056 +  5 + x] |= t;
  1121:             sprBuffer[1056 +  6 + x] |= t;
  1122:             sprBuffer[1056 +  7 + x] |= t;
  1123:             sprBuffer[1056 +  8 + x] |= t;
  1124:             sprBuffer[1056 +  9 + x] |= t;
  1125:             sprBuffer[1056 + 10 + x] |= t;
  1126:             sprBuffer[1056 + 11 + x] |= t;
  1127:             sprBuffer[1056 + 12 + x] |= t;
  1128:             sprBuffer[1056 + 13 + x] |= t;
  1129:             sprBuffer[1056 + 14 + x] |= t;
  1130:             sprBuffer[1056 + 15 + x] |= t;
  1131:           }  //if パレットブロックが0でないとき
  1132:           x += 16;
  1133:           sx = (sx + 1) & 63;
  1134:         }  //while x<width16
  1135:       }
  1136:     }  //if 水平256ドット/水平512ドット
  1137:   }  //sprStep2(int)
  1138: 
  1139:   //sprStep3 ()
  1140:   //  スプライトとバックグラウンドを重ねる
  1141:   //
  1142:   //  sprBuffer[2112 + x]
  1143:   //    4bitパレット
  1144:   //             28  24  20  16  12   8   4   0
  1145:   //    手前← |---|SP3|BG0|SP2|BG1|SP1|---|---| →奥
  1146:   //
  1147:   //  sprBuffer[1056 + x]
  1148:   //    パレットブロック
  1149:   //             28  24  20  16  12   8   4   0
  1150:   //    手前← |---|SP3|BG0|SP2|BG1|SP1|---|---| →奥
  1151:   //
  1152:   //  sprBuffer[x]
  1153:   //    8bitパレット
  1154:   //
  1155:   //!!! if (SPR_THREE_STEPS)
  1156:   public static void sprStep3 () {
  1157:     int width16 = 16 + XEiJ.pnlScreenWidth;
  1158:     if (!sprActive ||
  1159:         (sprReg4BgCtrlCurr & 512) == 0) {  //スプライト画面が表示されていない
  1160:       Arrays.fill (sprBuffer, 16, width16, 0);
  1161:     } else {  //スプライト画面が表示されている
  1162:       int mask = (15 << 24 |  //スプライト(プライオリティ3)
  1163:                   15 << 16 |  //スプライト(プライオリティ2)
  1164:                   15 << 8 |  //スプライト(プライオリティ1)
  1165:                   15 << 20 & -(sprReg4BgCtrlCurr & 1) |  //BG0。スプライト(プライオリティ3)とスプライト(プライオリティ2)の間
  1166:                   15 << 12 & -(sprReg4BgCtrlCurr & 8));  //BG1。スプライト(プライオリティ2)とスプライト(プライオリティ1)の間
  1167:       for (int x = 16; x < width16; x++) {  //X座標。画面左端は16
  1168:         int l = sprBuffer[2112 + x];  //4bitパレット
  1169:         int h = sprBuffer[1056 + x];  //パレットブロック
  1170:         if ((l &= mask) != 0) {  //4bitパレットが0でないプレーンがある
  1171:           int i = Integer.numberOfLeadingZeros (l) & -4;  //一番手前にあるものを選ぶ
  1172:           sprBuffer[x] = h << i >>> 28 << 4 | l << i >>> 28;  //パレットブロックと4bitパレットを合わせて8bitパレットを作る
  1173:         } else if ((h &= mask & (15 << 20 | 15 << 12)) != 0) {  //パレットブロックが0でないバックグラウンドプレーンがある
  1174:           int i = Integer.numberOfTrailingZeros (h) & -4;  //一番奥にあるものを選ぶ
  1175:           sprBuffer[x] = (h >> i & 15) << 4 | l >> i & 15;  //パレットブロックと4bitパレットを合わせて8bitパレットを作る
  1176:         } else {  //4bitパレットとパレットブロックがすべて0
  1177:           sprBuffer[x] = 0;
  1178:         }
  1179:       }  //for x
  1180:     }
  1181:   }  //sprStep3()
  1182: 
  1183: 
  1184: 
  1185:   //d = sprReadByte (a)
  1186:   //  リードバイト
  1187:   public static int sprReadByte (int a) throws M68kException {
  1188:     return ((a & 1) == 0 ?
  1189:             sprReadWord (a) >> 8 :
  1190:             sprReadWord (a & ~1) & 0x00ff);
  1191:   }  //sprReadByte
  1192: 
  1193:   //d = sprReadWord (a)
  1194:   //  リードワード
  1195:   public static int sprReadWord (int a) throws M68kException {
  1196:     a &= XEiJ.BUS_MOTHER_MASK;
  1197:     if (a < 0x00eb0800 || (0x00eb0840 <= a && a < 0x00eb4000)) {  //$00EB0000~$00EB07FF/$00EB0840~$00EB3FFF スプライトスクロールレジスタ
  1198:       //  アクセスできないとき
  1199:       //    バスエラーを返す
  1200:       //  ウェイトを追加する
  1201:       //  スプライト番号が範囲外のとき
  1202:       //    0xffffを返す
  1203:       //  スプライトスクロールレジスタを読み出して返す
  1204:       if (!sprAccessible) {  //アクセスできないとき
  1205:         return MemoryMappedDevice.MMD_NUL.mmdRwz (a);  //バスエラーを返す
  1206:       }
  1207:       //ウェイトを追加する
  1208:       XEiJ.mpuClockTime += sprWaitSprite;
  1209:       int n = (a - 0x00eb0000) >> 3;  //スプライト番号
  1210:       if (sprNumberOfSprites <= n) {  //スプライト番号が範囲外のとき
  1211:         if (SPR_RC_SCROLL_ON && sprRcScrollOn) {
  1212:           if (0x00eb2000 <= a && a < 0x00eb20ff) {  //行スクロールレジスタBG0,BG1
  1213:             return sprRowScroll[(a >> 1) & (64 * 4 - 1)];
  1214:           } else if (0x00eb2200 <= a && a < 0x00eb22ff) {  //列スクロールレジスタBG0,BG1
  1215:             return sprColScroll[(a >> 1) & (64 * 4 - 1)];
  1216:           }
  1217:         }
  1218:         return 0xffff;  //0xffffを返す
  1219:       }
  1220:       //スプライトスクロールレジスタを読み出して返す
  1221:       switch (a & 6) {
  1222:       case 0:
  1223:         return sprX[n];  //x座標
  1224:       case 2:
  1225:         return sprY[n];  //y座標
  1226:       case 4:
  1227:         {
  1228:           int v = sprV[n] ? 0x8000 : 0;  //上下反転<<15
  1229:           int h = sprH[n] ? 0x4000 : 0;  //左右反転<<14
  1230:           int col = sprColPort[n] << 4;  //(パレットブロック<<4)<<4
  1231:           int num = sprNum[n];  //パターン番号
  1232:           if (sprBankOn) {  //4096個のパターンが有効
  1233:             if (sprBankMode == 0) {  //256個
  1234:               return (v | h | col | num);
  1235:             } else if (sprBankMode == 1) {  //1024個
  1236:               return (v | h | (num & 0x0300) << 4 | col | (num & 0x00ff));
  1237:             } else {  //4096個
  1238:               return ((num & 0x0f00) << 4 | col | (num & 0x00ff));
  1239:             }
  1240:           } else {  //4096個のパターンが無効
  1241:             return (v | h | col | num);
  1242:           }
  1243:         }
  1244:       default:
  1245:         if (sprBankOn &&  //4096個のパターンが有効かつ
  1246:             sprBankMode == 3) {  //4096個反転あり
  1247:           return ((sprV[n] ? 0x8000 : 0) |  //上下反転<<15
  1248:                   (sprH[n] ? 0x4000 : 0) |  //左右反転<<14
  1249:                   (sprF[n] & 0x0004) |  //XPC1/PCS1
  1250:                   sprPrw[n]);  //プライオリティ
  1251:         } else {  //4096個のパターンが無効または(4096個反転あり)でない
  1252:           return ((sprF[n] & 0x0004) |  //XPC1/PCS1
  1253:                   sprPrw[n]);  //プライオリティ
  1254:         }
  1255:       }  //switch a&6
  1256:     } else if (a < 0x00eb4000) {  //$00EB0800~$00EB083F 各種レジスタ
  1257:       //  レジスタがあるとき
  1258:       //    レジスタの値を返す
  1259:       //  0xffffを返す
  1260:       switch (a) {
  1261:       case SPR_REG0_BG0_X:
  1262:         return sprReg0Bg0XPort;
  1263:       case SPR_REG1_BG0_Y:
  1264:         return sprReg1Bg0YPort;
  1265:       case SPR_REG2_BG1_X:
  1266:         return sprReg2Bg1XPort;
  1267:       case SPR_REG3_BG1_Y:
  1268:         return sprReg3Bg1YPort;
  1269:       case SPR_REG4_BG_CTRL:
  1270:         return sprReg4BgCtrlPort;
  1271:       case SPR_REG5_H_FRONT_END:
  1272:         return sprReg5HFrontEndPort;
  1273:       case SPR_REG6_H_BACK_END:
  1274:         return sprReg6HBackEndPort;
  1275:       case SPR_REG7_V_BACK_END:
  1276:         return sprReg7VBackEndPort;
  1277:       case SPR_REG8_RESO:
  1278:         return sprReg8ResoPort;
  1279:       case SPR_REG9_BANK_CONTROL:  //バンク制御
  1280:         if (sprBankOn) {  //4096個のパターンが有効
  1281:           return sprBankMode << 1 | (sprBankShifted ? 1 : 0);  //モード<<1|移動
  1282:         } else {  //4096個のパターンが無効
  1283:           return 0xffff;
  1284:         }
  1285:       case SPR_REG10_BANK_SELECT:  //バンク選択
  1286:         if (sprBankOn) {  //4096個のパターンが有効
  1287:           return sprBankNumber;  //バンク番号<<8
  1288:         } else {  //4096個のパターンが無効
  1289:           return 0xffff;
  1290:         }
  1291:       }
  1292:       return 0xffff;
  1293:     } else if (a < 0x00eb8000) {  //$00EB4000~$00EB7FFF テキストエリア
  1294:       //  4096個のパターンが有効かつ移動あり
  1295:       //    アクセスできないとき
  1296:       //      バスエラーを返す
  1297:       //    ウェイトを追加する
  1298:       //    テキストエリアを読み出して返す
  1299:       //  0xffffを返す
  1300:       if (sprBankOn &&  //4096個のパターンが有効かつ
  1301:           sprBankShifted) {  //移動あり
  1302:         if (!sprAccessible) {  //アクセスできないとき
  1303:           return MemoryMappedDevice.MMD_NUL.mmdRwz (a);  //バスエラーを返す
  1304:         }
  1305:         //ウェイトを追加する
  1306:         XEiJ.mpuClockTime += sprWaitPattern;
  1307:         //テキストエリアを読み出して返す
  1308:         int p = (a >> 1) & 8191;  //(4096*テキスト)+位置
  1309:         int v = sprTV[p] ? 0x8000 : 0;  //上下反転
  1310:         int h = sprTH[p] ? 0x4000 : 0;  //左右反転
  1311:         int col = sprTColPort[p] << 4;  //(パレットブロック<<4)<<4
  1312:         int num = sprTNum[p] >> 3;  //パターン番号
  1313:         if (sprBankOn) {  //4096個のパターンが有効
  1314:           if (sprBankMode == 0) {  //256個
  1315:             return (v | h | col | num);
  1316:           } else if (sprBankMode == 1) {  //1024個
  1317:             return (v | h | (num & 0x0300) << 4 | col | (num & 0x00ff));
  1318:           } else {  //4096個
  1319:             return ((num & 0x0f00) << 4 | col | (num & 0x00ff));
  1320:           }
  1321:         } else {  //4096個のパターンが無効
  1322:           return (v | h | col | num);
  1323:         }
  1324:       }  //if 4096個のパターンが有効かつテキストエリアが移動しているとき
  1325:       return 0xffff;
  1326:     } else {  //$00EB8000~$00EBFFFF パターンエリアとテキストエリア
  1327:       //  アクセスできないとき
  1328:       //    バスエラーを返す
  1329:       //  ウェイトを追加する
  1330:       //  XPC1/PCS1が選択されているとき
  1331:       //    0xffffを返す
  1332:       //  パターンエリアを読み出して返す
  1333:       if (!sprAccessible) {  //アクセスできないとき
  1334:         return MemoryMappedDevice.MMD_NUL.mmdRwz (a);  //バスエラーを返す
  1335:       }
  1336:       //ウェイトを追加する
  1337:       XEiJ.mpuClockTime += sprWaitPattern;
  1338:       if ((sprReg4BgCtrlPort & 0x0400) != 0) {  //XPC1/PCS1が選択されているとき
  1339:         return 0xffff;
  1340:       }
  1341:       //パターンエリアを読み出して返す
  1342:       int i = (a >> 2) & 8191;  //(パターン番号<<5)+int[]インデックス
  1343:       if (sprBankOn) {  //4096個のパターンが有効
  1344:         i += sprBankNumber << 5;  //(バンク番号<<8)<<5
  1345:       }
  1346:       return ((a & 2) == 0 ?
  1347:               sprPatPort[i] >>> 16 :
  1348:               (char) sprPatPort[i]);
  1349:     }
  1350:   }  //sprReadWord
  1351: 
  1352:   //d = sprReadLong (a)
  1353:   //  リードロング
  1354:   public static int sprReadLong (int a) throws M68kException {
  1355:     return (sprReadWord (a) << 16 |
  1356:             sprReadWord (a + 2));
  1357:   }  //sprReadLong
  1358: 
  1359: 
  1360: 
  1361:   //sprWriteByte (a, d)
  1362:   //  ライトバイト
  1363:   public static void sprWriteByte (int a, int d) throws M68kException {
  1364:     a &= XEiJ.BUS_MOTHER_MASK;
  1365:     if (a < 0x00eb0800 ||  //スプライトスクロールレジスタ
  1366:         (sprBankOn && sprBankShifted ? 0x00eb4000 : 0x00eb8000) <= a) {  //パターンエリアとテキストエリア
  1367:       sprWriteWord (a & ~1, d << 8 | (d & 0x00ff));  //上位バイトと下位バイトに同じ値を書き込む
  1368:     } else {  //各種レジスタ
  1369:       if ((a & 1) == 0) {
  1370:         sprWriteWord (a, d << 8 | (sprReadWord (a) & 0x00ff));
  1371:       } else {
  1372:         sprWriteWord (a & ~1, (sprReadWord (a & ~1) & 0xff00) | (d & 0x00ff));
  1373:       }
  1374:     }
  1375:   }  //sprWriteByte
  1376: 
  1377:   //sprWriteWord (a, d)
  1378:   //  ライトワード
  1379:   public static void sprWriteWord (int a, int d) throws M68kException {
  1380:     a &= XEiJ.BUS_MOTHER_MASK;
  1381:     if (a < 0x00eb0800 || (0x00eb0840 <= a && a < 0x00eb4000)) {  //$00EB0000~$00EB07FF/$00EB0840~$00EB3FFF スプライトスクロールレジスタ
  1382:       //  アクセスできないとき
  1383:       //    バスエラー
  1384:       //    終了
  1385:       //  ウェイトを追加する
  1386:       //  スプライト番号が範囲外のとき
  1387:       //    終了
  1388:       //  スプライトスクロールレジスタへ書き込む
  1389:       //  終了
  1390:       if (!sprAccessible) {  //アクセスできないとき
  1391:         MemoryMappedDevice.MMD_NUL.mmdWw (a, d);  //バスエラー
  1392:         return;
  1393:       }
  1394:       //ウェイトを追加する
  1395:       XEiJ.mpuClockTime += sprWaitSprite;
  1396:       int n = (a - 0x00eb0000) >> 3;  //スプライト番号
  1397:       if (sprNumberOfSprites <= n) {  //スプライト番号が範囲外のとき
  1398:         if (SPR_RC_SCROLL_ON && sprRcScrollOn) {
  1399:           if (0x00eb2000 <= a && a < 0x00eb20ff) {  //行スクロールレジスタBG0,BG1
  1400:             sprRowScroll[(a >> 1) & (64 * 4 - 1)] = d & 1023;
  1401:           } else if (0x00eb2200 <= a && a < 0x00eb22ff) {  //列スクロールレジスタBG0,BG1
  1402:             sprColScroll[(a >> 1) & (64 * 4 - 1)] = d & 1023;
  1403:           }
  1404:         }
  1405:         return;
  1406:       }
  1407:       //スプライトスクロールレジスタへ書き込む
  1408:       switch (a & 6) {
  1409:       case 0:
  1410:         sprX[n] = (short) (d & 1023);  //x座標
  1411:         return;
  1412:       case 2:
  1413:         d &= 1023;
  1414:         if (sprY[n] != d) {
  1415:           int y = sprY[n];  //元のy座標
  1416:           sprY[n] = (short) d;  //y座標
  1417:           if (sprPrw[n] != 0) {
  1418:             int mask = ~(0x80000000 >>> n);  //intのシフトカウントは5bitでマスクされる
  1419:             int i = y << (SPR_SHIFT - 5) | n >> 5;  //移動元
  1420:             sprRRmap[i                          ] &= mask;
  1421:             sprRRmap[i + ( 1 << (SPR_SHIFT - 5))] &= mask;
  1422:             sprRRmap[i + ( 2 << (SPR_SHIFT - 5))] &= mask;
  1423:             sprRRmap[i + ( 3 << (SPR_SHIFT - 5))] &= mask;
  1424:             sprRRmap[i + ( 4 << (SPR_SHIFT - 5))] &= mask;
  1425:             sprRRmap[i + ( 5 << (SPR_SHIFT - 5))] &= mask;
  1426:             sprRRmap[i + ( 6 << (SPR_SHIFT - 5))] &= mask;
  1427:             sprRRmap[i + ( 7 << (SPR_SHIFT - 5))] &= mask;
  1428:             sprRRmap[i + ( 8 << (SPR_SHIFT - 5))] &= mask;
  1429:             sprRRmap[i + ( 9 << (SPR_SHIFT - 5))] &= mask;
  1430:             sprRRmap[i + (10 << (SPR_SHIFT - 5))] &= mask;
  1431:             sprRRmap[i + (11 << (SPR_SHIFT - 5))] &= mask;
  1432:             sprRRmap[i + (12 << (SPR_SHIFT - 5))] &= mask;
  1433:             sprRRmap[i + (13 << (SPR_SHIFT - 5))] &= mask;
  1434:             sprRRmap[i + (14 << (SPR_SHIFT - 5))] &= mask;
  1435:             sprRRmap[i + (15 << (SPR_SHIFT - 5))] &= mask;
  1436:             mask = ~mask;
  1437:             i = d << (SPR_SHIFT - 5) | n >> 5;  //移動先
  1438:             sprRRmap[i                          ] |= mask;
  1439:             sprRRmap[i + ( 1 << (SPR_SHIFT - 5))] |= mask;
  1440:             sprRRmap[i + ( 2 << (SPR_SHIFT - 5))] |= mask;
  1441:             sprRRmap[i + ( 3 << (SPR_SHIFT - 5))] |= mask;
  1442:             sprRRmap[i + ( 4 << (SPR_SHIFT - 5))] |= mask;
  1443:             sprRRmap[i + ( 5 << (SPR_SHIFT - 5))] |= mask;
  1444:             sprRRmap[i + ( 6 << (SPR_SHIFT - 5))] |= mask;
  1445:             sprRRmap[i + ( 7 << (SPR_SHIFT - 5))] |= mask;
  1446:             sprRRmap[i + ( 8 << (SPR_SHIFT - 5))] |= mask;
  1447:             sprRRmap[i + ( 9 << (SPR_SHIFT - 5))] |= mask;
  1448:             sprRRmap[i + (10 << (SPR_SHIFT - 5))] |= mask;
  1449:             sprRRmap[i + (11 << (SPR_SHIFT - 5))] |= mask;
  1450:             sprRRmap[i + (12 << (SPR_SHIFT - 5))] |= mask;
  1451:             sprRRmap[i + (13 << (SPR_SHIFT - 5))] |= mask;
  1452:             sprRRmap[i + (14 << (SPR_SHIFT - 5))] |= mask;
  1453:             sprRRmap[i + (15 << (SPR_SHIFT - 5))] |= mask;
  1454:           }
  1455:         }
  1456:         return;
  1457:       case 4:
  1458:         {
  1459:           int preNum = sprNum[n];  //変更前のパターン番号
  1460:           int col = (d & 0x0f00) >> 4;  //パレットブロック<<4
  1461:           int num = (d & 0x00ff);  //パターン番号の下位8bit
  1462:           if (sprBankOn) {  //4096個のパターンが有効
  1463:             if (sprBankMode <= 1) {  //256個または1024個
  1464:               sprV[n] = (d & 0x8000) != 0;  //上下反転
  1465:               sprH[n] = (d & 0x4000) != 0;  //左右反転
  1466:               if (sprBankMode == 1) {  //1024個
  1467:                 num |= (d & 0x3000) >> 4;  //パターン番号の上位2bit
  1468:               }
  1469:             } else  {  //4096個
  1470:               //4096個反転ありのときここでは反転を操作しない
  1471:               if (sprBankMode == 2) {  //反転なし
  1472:                 sprV[n] = false;  //上下反転
  1473:                 sprH[n] = false;  //左右反転
  1474:               }
  1475:               num |= (d & 0xf000) >> 4;  //パターン番号の上位4bit
  1476:             }
  1477:           } else {  //4096個のパターンが無効
  1478:             sprV[n] = (d & 0x8000) != 0;  //上下反転
  1479:             sprH[n] = (d & 0x4000) != 0;  //左右反転
  1480:           }
  1481:           sprColPort[n] = (short) col;  //パレットブロック<<4
  1482:           sprNum[n] = (short) num;  //パターン番号
  1483:           if (sprPrw[n] != 0 && preNum != num) {  //表示されているかつパターン番号が変わった
  1484:             int mask = 0x80000000 >>> n;  //intのシフトカウントは5bitでマスクされる
  1485:             sprPPmap[preNum << (SPR_SHIFT - 5) | n >> 5] &= ~mask;  //消滅
  1486:             sprPPmap[num << (SPR_SHIFT - 5) | n >> 5] |= mask;  //出現
  1487:           }
  1488:         }
  1489:         return;
  1490:       default:
  1491:         {
  1492:           if (sprBankOn &&  //4096個のパターンが有効かつ
  1493:               sprBankMode == 3) {  //4096個反転あり
  1494:             //4096個反転ありのときここで反転を操作する
  1495:             sprV[n] = (d & 0x8000) != 0;  //上下反転<<15
  1496:             sprH[n] = (d & 0x4000) != 0;  //左右反転<<14
  1497:           }
  1498:           int prePrw = sprPrw[n];  //変更前のプライオリティ
  1499:           int prw = (d & 0x0003);
  1500:           sprPrw[n] = (byte) prw;  //プライオリティ
  1501:           if (prePrw == 0 && prw != 0) {  //出現
  1502:             int y = sprY[n];
  1503:             int mask = 0x80000000 >>> n;  //intのシフトカウントは5bitでマスクされる
  1504:             int i = y << (SPR_SHIFT - 5) | n >> 5;
  1505:             sprRRmap[i                          ] |= mask;
  1506:             sprRRmap[i + ( 1 << (SPR_SHIFT - 5))] |= mask;
  1507:             sprRRmap[i + ( 2 << (SPR_SHIFT - 5))] |= mask;
  1508:             sprRRmap[i + ( 3 << (SPR_SHIFT - 5))] |= mask;
  1509:             sprRRmap[i + ( 4 << (SPR_SHIFT - 5))] |= mask;
  1510:             sprRRmap[i + ( 5 << (SPR_SHIFT - 5))] |= mask;
  1511:             sprRRmap[i + ( 6 << (SPR_SHIFT - 5))] |= mask;
  1512:             sprRRmap[i + ( 7 << (SPR_SHIFT - 5))] |= mask;
  1513:             sprRRmap[i + ( 8 << (SPR_SHIFT - 5))] |= mask;
  1514:             sprRRmap[i + ( 9 << (SPR_SHIFT - 5))] |= mask;
  1515:             sprRRmap[i + (10 << (SPR_SHIFT - 5))] |= mask;
  1516:             sprRRmap[i + (11 << (SPR_SHIFT - 5))] |= mask;
  1517:             sprRRmap[i + (12 << (SPR_SHIFT - 5))] |= mask;
  1518:             sprRRmap[i + (13 << (SPR_SHIFT - 5))] |= mask;
  1519:             sprRRmap[i + (14 << (SPR_SHIFT - 5))] |= mask;
  1520:             sprRRmap[i + (15 << (SPR_SHIFT - 5))] |= mask;
  1521:             sprPPmap[sprNum[n] << (SPR_SHIFT - 5) | n >> 5] |= mask;
  1522:           } else if (prePrw != 0 && prw == 0) {  //消滅
  1523:             int y = sprY[n];
  1524:             int mask = ~(0x80000000 >>> n);  //intのシフトカウントは5bitでマスクされる
  1525:             int i = y << (SPR_SHIFT - 5) | n >> 5;
  1526:             sprRRmap[i                          ] &= mask;
  1527:             sprRRmap[i + ( 1 << (SPR_SHIFT - 5))] &= mask;
  1528:             sprRRmap[i + ( 2 << (SPR_SHIFT - 5))] &= mask;
  1529:             sprRRmap[i + ( 3 << (SPR_SHIFT - 5))] &= mask;
  1530:             sprRRmap[i + ( 4 << (SPR_SHIFT - 5))] &= mask;
  1531:             sprRRmap[i + ( 5 << (SPR_SHIFT - 5))] &= mask;
  1532:             sprRRmap[i + ( 6 << (SPR_SHIFT - 5))] &= mask;
  1533:             sprRRmap[i + ( 7 << (SPR_SHIFT - 5))] &= mask;
  1534:             sprRRmap[i + ( 8 << (SPR_SHIFT - 5))] &= mask;
  1535:             sprRRmap[i + ( 9 << (SPR_SHIFT - 5))] &= mask;
  1536:             sprRRmap[i + (10 << (SPR_SHIFT - 5))] &= mask;
  1537:             sprRRmap[i + (11 << (SPR_SHIFT - 5))] &= mask;
  1538:             sprRRmap[i + (12 << (SPR_SHIFT - 5))] &= mask;
  1539:             sprRRmap[i + (13 << (SPR_SHIFT - 5))] &= mask;
  1540:             sprRRmap[i + (14 << (SPR_SHIFT - 5))] &= mask;
  1541:             sprRRmap[i + (15 << (SPR_SHIFT - 5))] &= mask;
  1542:             sprPPmap[sprNum[n] << (SPR_SHIFT - 5) | n >> 5] &= mask;
  1543:           }
  1544:           sprF[n] = (d & 0x0004) != 0 ? -1 : 0;  //XPC1/PCS1
  1545:         }
  1546:         return;
  1547:       }  //switch a&6
  1548:     } else if (a < 0x00eb4000) {  //$00EB0800~$00EB083F 各種レジスタ
  1549:       //  レジスタがあるとき
  1550:       //    レジスタへ書き込む
  1551:       //    終了
  1552:       //  終了
  1553:       switch (a) {
  1554:       case SPR_REG0_BG0_X:
  1555:         sprReg0Bg0XPort = (d & 1023);
  1556:         {
  1557:           int curr = sprReg0Bg0XMask == 0 ? sprReg0Bg0XPort : sprReg0Bg0XTest;
  1558:           if (sprReg0Bg0XCurr != curr) {
  1559:             sprReg0Bg0XCurr = curr;
  1560:           }
  1561:         }
  1562:         return;
  1563:       case SPR_REG1_BG0_Y:
  1564:         sprReg1Bg0YPort = (d & 1023);
  1565:         {
  1566:           int curr = sprReg1Bg0YMask == 0 ? sprReg1Bg0YPort : sprReg1Bg0YTest;
  1567:           if (sprReg1Bg0YCurr != curr) {
  1568:             sprReg1Bg0YCurr = curr;
  1569:           }
  1570:         }
  1571:         return;
  1572:       case SPR_REG2_BG1_X:
  1573:         sprReg2Bg1XPort = (d & 1023);
  1574:         {
  1575:           int curr = sprReg2Bg1XMask == 0 ? sprReg2Bg1XPort : sprReg2Bg1XTest;
  1576:           if (sprReg2Bg1XCurr != curr) {
  1577:             sprReg2Bg1XCurr = curr;
  1578:           }
  1579:         }
  1580:         return;
  1581:       case SPR_REG3_BG1_Y:
  1582:         sprReg3Bg1YPort = (d & 1023);
  1583:         {
  1584:           int curr = sprReg3Bg1YMask == 0 ? sprReg3Bg1YPort : sprReg3Bg1YTest;
  1585:           if (sprReg3Bg1YCurr != curr) {
  1586:             sprReg3Bg1YCurr = curr;
  1587:           }
  1588:         }
  1589:         return;
  1590:       case SPR_REG4_BG_CTRL:  //$00EB0808
  1591:         sprReg4BgCtrlPort = (d & 0x063f);
  1592:         {
  1593:           int curr = sprReg4BgCtrlPort & ~sprReg4BgCtrlMask | sprReg4BgCtrlTest & sprReg4BgCtrlMask;
  1594:           if (sprReg4BgCtrlCurr != curr) {
  1595:             sprReg4BgCtrlCurr = curr;
  1596:             if ((sprReg4BgCtrlCurr & 512) == 0) {  //DISP=0
  1597:               sprWaitSprite = SPR_WAIT_SPRITE_DISP_0;
  1598:               sprWaitPattern = SPR_WAIT_PATTERN_DISP_0;
  1599:             } else {  //DISP=1
  1600:               sprWaitSprite = SPR_WAIT_SPRITE_DISP_1;
  1601:               sprWaitPattern = SPR_WAIT_PATTERN_DISP_1;
  1602:               if (SPR_THREE_STEPS) {
  1603:                 sprLatched = true;
  1604:               }
  1605:             }
  1606:           }
  1607:         }
  1608:         return;
  1609:       case SPR_REG5_H_FRONT_END:
  1610:         sprReg5HFrontEndPort = (d & 255);
  1611:         {
  1612:           int curr = sprReg5HFrontEndMask == 0 ? sprReg5HFrontEndPort : sprReg5HFrontEndTest;
  1613:           if (sprReg5HFrontEndCurr != curr) {
  1614:             sprReg5HFrontEndCurr = curr;
  1615:           }
  1616:         }
  1617:         return;
  1618:       case SPR_REG6_H_BACK_END:
  1619:         sprReg6HBackEndPort = (d & 63);
  1620:         {
  1621:           int curr = sprReg6HBackEndMask == 0 ? sprReg6HBackEndPort : sprReg6HBackEndTest;
  1622:           if (sprReg6HBackEndCurr != curr) {
  1623:             sprReg6HBackEndCurr = curr;
  1624:           }
  1625:         }
  1626:         return;
  1627:       case SPR_REG7_V_BACK_END:
  1628:         sprReg7VBackEndPort = (d & 255);
  1629:         {
  1630:           int curr = sprReg7VBackEndMask == 0 ? sprReg7VBackEndPort : sprReg7VBackEndTest;
  1631:           if (sprReg7VBackEndCurr != curr) {
  1632:             sprReg7VBackEndCurr = curr;
  1633:           }
  1634:         }
  1635:         return;
  1636:       case SPR_REG8_RESO:
  1637:         sprReg8ResoPort = (d & 31);
  1638:         {
  1639:           int curr = sprReg8ResoPort & ~sprReg8ResoMask | sprReg8ResoTest & sprReg8ResoMask;
  1640:           if (sprReg8ResoCurr != curr) {
  1641:             sprReg8ResoCurr = curr;
  1642:             CRTC.crtRestart ();
  1643:           }
  1644:         }
  1645:         return;
  1646:       case SPR_REG9_BANK_CONTROL:
  1647:         if (sprBankOn) {  //4096個のパターンが有効
  1648:           sprBankMode = (d & 6) >> 1;  //モード
  1649:           sprBankShifted = (d & 1) != 0;  //移動
  1650:         }
  1651:         return;
  1652:       case SPR_REG10_BANK_SELECT:
  1653:         if (sprBankOn) {  //4096個のパターンが有効
  1654:           sprBankNumber = (d & (15 << 8));  //バンク番号<<8
  1655:         }
  1656:         return;
  1657:       }  //switch a
  1658:       return;
  1659:     } else if (a < 0x00eb8000) {  //$00EB4000~$00EB7FFF テキストエリア
  1660:       //  4096個のパターンが有効かつ移動あり
  1661:       //    アクセスできないとき
  1662:       //      バスエラーで終了
  1663:       //    ウェイトを追加する
  1664:       //    テキストエリアへ書き込んで終了
  1665:       //  終了
  1666:       if (sprBankOn &&  //4096個のパターンが有効かつ
  1667:           sprBankShifted) {  //移動あり
  1668:         if (!sprAccessible) {  //アクセスできないとき
  1669:           MemoryMappedDevice.MMD_NUL.mmdWw (a, d);  //バスエラーで終了
  1670:           return;
  1671:         }
  1672:         //ウェイトを追加する
  1673:         XEiJ.mpuClockTime += sprWaitPattern;
  1674:         //テキストエリアへ書き込んで終了
  1675:         boolean v = (d & 0x8000) != 0;  //上下反転
  1676:         boolean h = (d & 0x4000) != 0;  //左右反転
  1677:         int col = (d & 0x0f00) >> 4;  //パレットブロック<<4
  1678:         int num = (d & 0x00ff);  //パターン番号の下位8bit
  1679:         if (sprBankMode == 0) {  //256個
  1680:         } else if (sprBankMode == 1) {  //1024個
  1681:           num |= (d & 0x3000) >> 4;  //パターン番号の上位2bit
  1682:         } else {  //4096個。反転は無効
  1683:           v = false;  //上下反転
  1684:           h = false;  //左右反転
  1685:           num |= (d & 0xf000) >> 4;  //パターン番号の上位4bit
  1686:         }
  1687:         int p = (a >> 1) & 8191;  //(4096*テキスト)+位置
  1688:         sprTV[p] = v;  //上下反転
  1689:         sprTH[p] = h;  //左右反転
  1690:         sprTColPort[p] = (short) col;  //パレットブロック<<4
  1691:         sprTNum[p] = (short) (num << 3);  //パターン番号<<3
  1692:         return;
  1693:       }
  1694:       return;
  1695:     } else if (a < 0x00ebc000) {  //$00EB8000~$00EBBFFF パターンエリア
  1696:       //  アクセスできないとき
  1697:       //    バスエラー
  1698:       //    終了
  1699:       //  ウェイトを追加する
  1700:       //  XPC1/PCS1が選択されているとき
  1701:       //    終了
  1702:       //  パターンエリアへ書き込む
  1703:       //  終了
  1704:       if (!sprAccessible) {  //アクセスできないとき
  1705:         MemoryMappedDevice.MMD_NUL.mmdWw (a, d);  //バスエラー
  1706:         return;
  1707:       }
  1708:       //ウェイトを追加する
  1709:       XEiJ.mpuClockTime += sprWaitPattern;
  1710:       if ((sprReg4BgCtrlPort & 0x0400) != 0) {  //XPC1/PCS1が選択されているとき
  1711:         return;
  1712:       }
  1713:       //パターンエリアへ書き込む
  1714:       int i = ((a >> 2) & 8191);  //(パターン番号<<5)+int[]インデックス
  1715:       if (sprBankOn) {  //4096個のパターンが有効
  1716:         i += sprBankNumber << 5;  //(バンク番号<<8)<<5
  1717:       }
  1718:       sprPatPort[i] = ((a & 2) == 0 ?
  1719:                        d << 16 | (char) sprPatPort[i] :
  1720:                        (sprPatPort[i] & 0xffff0000) | (char) d);
  1721:       return;
  1722:     } else {  //$00EBC000~$00EBFFFF パターンエリアとテキストエリア
  1723:       //  アクセスできないとき
  1724:       //    バスエラー
  1725:       //    終了
  1726:       //  ウェイトを追加する
  1727:       //  XPC1/PCS1が選択されているとき
  1728:       //    終了
  1729:       //  パターンエリアへ書き込む
  1730:       //  4096個のパターンが無効または移動なしかつバンク番号が0のとき
  1731:       //    テキストエリアへ書き込む
  1732:       //    終了
  1733:       //  終了
  1734:       if (!sprAccessible) {  //アクセスできないとき
  1735:         MemoryMappedDevice.MMD_NUL.mmdWw (a, d);  //バスエラー
  1736:         return;
  1737:       }
  1738:       //ウェイトを追加する
  1739:       XEiJ.mpuClockTime += sprWaitPattern;
  1740:       if ((sprReg4BgCtrlPort & 0x0400) != 0) {  //XPC1/PCS1が選択されているとき
  1741:         return;
  1742:       }
  1743:       //パターンエリアへ書き込む
  1744:       int i = ((a >> 2) & 8191);  //(パターン番号<<5)+int[]インデックス
  1745:       if (sprBankOn) {  //4096個のパターンが有効
  1746:         i += sprBankNumber << 5;  //(バンク番号<<8)<<5
  1747:       }
  1748:       sprPatPort[i] = ((a & 2) == 0 ?
  1749:                        d << 16 | (char) sprPatPort[i] :
  1750:                        (sprPatPort[i] & 0xffff0000) | (char) d);
  1751:       if (!sprBankOn ||  //4096個のパターンが無効または
  1752:           (!sprBankShifted && sprBankNumber == (0 << 8))) {  //移動なしかつバンク番号が0のとき
  1753:         //テキストエリアへ書き込む
  1754:         boolean v = (d & 0x8000) != 0;  //上下反転
  1755:         boolean h = (d & 0x4000) != 0;  //左右反転
  1756:         int col = (d & 0x0f00) >> 4;  //パレットブロック<<4
  1757:         int num = (d & 0x00ff);  //パターン番号の下位8bit
  1758:         if (sprBankOn) {  //4096個のパターンが有効
  1759:           if (sprBankMode == 0) {  //256個
  1760:           } else if (sprBankMode == 1) {  //1024個
  1761:             num |= (d & 0x3000) >> 4;  //パターン番号の上位2bit
  1762:           } else {  //4096個。反転は無効
  1763:             v = false;  //上下反転
  1764:             h = false;  //左右反転
  1765:             num |= (d & 0xf000) >> 4;  //パターン番号の上位4bit
  1766:           }
  1767:         }
  1768:         int p = (a >> 1) & 8191;  //(4096*テキスト)+位置
  1769:         sprTV[p] = v;  //上下反転
  1770:         sprTH[p] = h;  //左右反転
  1771:         sprTColPort[p] = (short) col;  //パレットブロック<<4
  1772:         sprTNum[p] = (short) (num << 3);  //パターン番号<<3
  1773:         return;
  1774:       }
  1775:       return;
  1776:     }
  1777:   }  //sprWriteWord
  1778: 
  1779:   //sprWriteLong (a, d)
  1780:   //  ライトロング
  1781:   public static void sprWriteLong (int a, int d) throws M68kException {
  1782:     sprWriteWord (a, d >> 16);
  1783:     sprWriteWord (a + 2, d);
  1784:   }  //sprWriteLong
  1785: 
  1786: 
  1787: 
  1788: }  //class SpriteScreen
  1789: 
  1790: 
  1791: