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