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