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