MemoryMappedDevice.java
     1: //========================================================================================
     2: //  MemoryMappedDevice.java
     3: //    en:Memory mapped device
     4: //    ja:メモリマップトデバイス
     5: //  Copyright (C) 2003-2017 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: //  http://stdkmd.com/xeij/
    11: //========================================================================================
    12: 
    13: //----------------------------------------------------------------------------------------
    14: //  デバイスにアクセスするためのメソッドをenum bodyに記述する
    15: //    mmdPbs,mmdPbz,mmdPws,mmdPwz,mmdPls  ピーク
    16: //    mmdRbs,mmdRbz,mmdRws,mmdRwz,mmdRls  リード
    17: //    mmdWb,mmdWw,mmdWl                   ライト
    18: //  ピーク、リード、ライトの命名規則
    19: //    4文字目  P=ピーク,R=リード,W=ライト
    20: //    5文字目  b=バイト,w=ワード,l=ロング
    21: //    6文字目  s=符号拡張,z=ゼロ拡張
    22: //  ピークとリードの返却値の型はmmdPbsとmmdRbsだけbyte、他はint
    23: //  ピークはSRAMスイッチの読み取りやデバッガなどで使用する
    24: //  ピークはMPUやデバイスの状態を変化させず、例外もスローしない
    25: //  リードとライトはMPUやDMAによる通常のアクセスで使用する
    26: //  リードとライトはバスエラーをスローする場合がある
    27: //  アドレスの未使用ビットはデバイスに渡る前にすべてクリアされていなければならない
    28: //    バスエラーは未使用ビットがクリアされたアドレスで通知されることになる
    29: //  異なるデバイスに跨るアクセスはデバイスに渡る前に分割されていなければならない
    30: //  奇数アドレスに対するワードアクセスはデバイスに渡る前に分割または排除されていなければならない
    31: //  4の倍数でないアドレスに対するロングアクセスはデバイスに渡る前に分割または排除されていなければならない
    32: //  デバイスのメソッドを直接呼び出すときはアドレスのマスクや分割を忘れないこと
    33: //----------------------------------------------------------------------------------------
    34: 
    35: package xeij;
    36: 
    37: import java.lang.*;  //Boolean,Character,Class,Comparable,Double,Exception,Float,IllegalArgumentException,Integer,Long,Math,Number,Object,Runnable,SecurityException,String,StringBuilder,System
    38: import java.util.*;  //ArrayList,Arrays,Calendar,GregorianCalendar,HashMap,Map,Map.Entry,Timer,TimerTask,TreeMap
    39: 
    40: public enum MemoryMappedDevice {
    41: 
    42:   //--------------------------------------------------------------------------------
    43:   //MMD_MMR メインメモリ
    44:   MMD_MMR {
    45:     @Override public String toString () {
    46:       return Multilingual.mlnJapanese ? "メインメモリ" : "Main Memory";
    47:     }
    48:     //ピーク
    49:     @Override protected byte mmdPbs (int a) {
    50:       a &= XEiJ.BUS_MOTHER_MASK;
    51:       return MainMemory.mmrM8[a];
    52:     }
    53:     @Override protected int mmdPbz (int a) {
    54:       a &= XEiJ.BUS_MOTHER_MASK;
    55:       return MainMemory.mmrM8[a] & 255;
    56:     }
    57:     @Override protected int mmdPws (int a) {
    58:       a &= XEiJ.BUS_MOTHER_MASK;
    59:       if (MainMemory.MMR_USE_BYTE_BUFFER) {
    60:         return MainMemory.mmrBuffer.getShort (a);
    61:       } else {
    62:         return MainMemory.mmrM8[a] << 8 | MainMemory.mmrM8[a + 1] & 255;
    63:       }
    64:     }
    65:     @Override protected int mmdPwz (int a) {
    66:       a &= XEiJ.BUS_MOTHER_MASK;
    67:       if (MainMemory.MMR_USE_BYTE_BUFFER) {
    68:         return MainMemory.mmrBuffer.getChar (a);
    69:       } else {
    70:         return (char) (MainMemory.mmrM8[a] << 8 | MainMemory.mmrM8[a + 1] & 255);
    71:       }
    72:     }
    73:     @Override protected int mmdPls (int a) {
    74:       a &= XEiJ.BUS_MOTHER_MASK;
    75:       if (MainMemory.MMR_USE_BYTE_BUFFER) {
    76:         return MainMemory.mmrBuffer.getInt (a);
    77:       } else {
    78:         return MainMemory.mmrM8[a] << 24 | (MainMemory.mmrM8[a + 1] & 255) << 16 | (char) (MainMemory.mmrM8[a + 2] << 8 | MainMemory.mmrM8[a + 3] & 255);
    79:       }
    80:     }
    81:     //リード
    82:     @Override protected byte mmdRbs (int a) throws M68kException {
    83:        a &= XEiJ.BUS_MOTHER_MASK;
    84:        return MainMemory.mmrM8[a];
    85:      }
    86:     @Override protected int mmdRbz (int a) throws M68kException {
    87:        a &= XEiJ.BUS_MOTHER_MASK;
    88:        return MainMemory.mmrM8[a] & 255;
    89:      }
    90:     @Override protected int mmdRws (int a) throws M68kException {
    91:        a &= XEiJ.BUS_MOTHER_MASK;
    92:        if (MainMemory.MMR_USE_BYTE_BUFFER) {
    93:          return MainMemory.mmrBuffer.getShort (a);
    94:        } else {
    95:          return MainMemory.mmrM8[a] << 8 | MainMemory.mmrM8[a + 1] & 255;
    96:        }
    97:      }
    98:     @Override protected int mmdRwz (int a) throws M68kException {
    99:        a &= XEiJ.BUS_MOTHER_MASK;
   100:        if (MainMemory.MMR_USE_BYTE_BUFFER) {
   101:          return MainMemory.mmrBuffer.getChar (a);
   102:        } else {
   103:          return (char) (MainMemory.mmrM8[a] << 8 | MainMemory.mmrM8[a + 1] & 255);
   104:        }
   105:      }
   106:     @Override protected int mmdRls (int a) throws M68kException {
   107:        a &= XEiJ.BUS_MOTHER_MASK;
   108:        if (MainMemory.MMR_USE_BYTE_BUFFER) {
   109:          return MainMemory.mmrBuffer.getInt (a);
   110:        } else {
   111:          return MainMemory.mmrM8[a] << 24 | (MainMemory.mmrM8[a + 1] & 255) << 16 | (char) (MainMemory.mmrM8[a + 2] << 8 | MainMemory.mmrM8[a + 3] & 255);
   112:        }
   113:      }
   114:     //ライト
   115:     @Override protected void mmdWb (int a, int d) throws M68kException {
   116:        a &= XEiJ.BUS_MOTHER_MASK;
   117:        MainMemory.mmrM8[a    ] = (byte)  d;
   118:      }
   119:     @Override protected void mmdWw (int a, int d) throws M68kException {
   120:        a &= XEiJ.BUS_MOTHER_MASK;
   121:        if (MainMemory.MMR_USE_BYTE_BUFFER) {
   122:          MainMemory.mmrBuffer.putShort (a, (short) d);
   123:        } else {
   124:          MainMemory.mmrM8[a    ] = (byte) (d >> 8);
   125:          MainMemory.mmrM8[a + 1] = (byte)  d;
   126:        }
   127:      }
   128:     @Override protected void mmdWl (int a, int d) throws M68kException {
   129:        a &= XEiJ.BUS_MOTHER_MASK;
   130:        if (MainMemory.MMR_USE_BYTE_BUFFER) {
   131:          MainMemory.mmrBuffer.putInt (a, d);
   132:        } else {
   133:          MainMemory.mmrM8[a    ] = (byte) (d >> 24);
   134:          MainMemory.mmrM8[a + 1] = (byte) (d >> 16);
   135:          MainMemory.mmrM8[a + 2] = (byte) (d >> 8);
   136:          MainMemory.mmrM8[a + 3] = (byte)  d;
   137:        }
   138:      }
   139:   },  //MMD_MMR
   140: 
   141:   //--------------------------------------------------------------------------------
   142:   //MMD_XMM 拡張メモリ
   143:   MMD_XMM {
   144:     @Override public String toString () {
   145:       return Multilingual.mlnJapanese ? "拡張メモリ" : "Expansion Memory";
   146:     }
   147:     //ピーク
   148:     @Override protected byte mmdPbs (int a) {
   149:       a -= XEiJ.busExMemoryStart;
   150:       return XEiJ.busExMemoryArray[a];
   151:     }
   152:     @Override protected int mmdPbz (int a) {
   153:       a -= XEiJ.busExMemoryStart;
   154:       return XEiJ.busExMemoryArray[a] & 255;
   155:     }
   156:     @Override protected int mmdPws (int a) {
   157:       a -= XEiJ.busExMemoryStart;
   158:       return XEiJ.busExMemoryArray[a] << 8 | XEiJ.busExMemoryArray[a + 1] & 255;
   159:     }
   160:     @Override protected int mmdPwz (int a) {
   161:       a -= XEiJ.busExMemoryStart;
   162:       return (char) (XEiJ.busExMemoryArray[a] << 8 | XEiJ.busExMemoryArray[a + 1] & 255);
   163:     }
   164:     @Override protected int mmdPls (int a) {
   165:       a -= XEiJ.busExMemoryStart;
   166:       return XEiJ.busExMemoryArray[a] << 24 | (XEiJ.busExMemoryArray[a + 1] & 255) << 16 | (char) (XEiJ.busExMemoryArray[a + 2] << 8 | XEiJ.busExMemoryArray[a + 3] & 255);
   167:     }
   168:     //リード
   169:     @Override protected byte mmdRbs (int a) throws M68kException {
   170:        a -= XEiJ.busExMemoryStart;
   171:        return XEiJ.busExMemoryArray[a];
   172:      }
   173:     @Override protected int mmdRbz (int a) throws M68kException {
   174:        a -= XEiJ.busExMemoryStart;
   175:        return XEiJ.busExMemoryArray[a] & 255;
   176:      }
   177:     @Override protected int mmdRws (int a) throws M68kException {
   178:        a -= XEiJ.busExMemoryStart;
   179:        return XEiJ.busExMemoryArray[a] << 8 | XEiJ.busExMemoryArray[a + 1] & 255;
   180:      }
   181:     @Override protected int mmdRwz (int a) throws M68kException {
   182:        a -= XEiJ.busExMemoryStart;
   183:        return (char) (XEiJ.busExMemoryArray[a] << 8 | XEiJ.busExMemoryArray[a + 1] & 255);
   184:      }
   185:     @Override protected int mmdRls (int a) throws M68kException {
   186:        a -= XEiJ.busExMemoryStart;
   187:        return XEiJ.busExMemoryArray[a] << 24 | (XEiJ.busExMemoryArray[a + 1] & 255) << 16 | (char) (XEiJ.busExMemoryArray[a + 2] << 8 | XEiJ.busExMemoryArray[a + 3] & 255);
   188:      }
   189:     //ライト
   190:     @Override protected void mmdWb (int a, int d) throws M68kException {
   191:        a -= XEiJ.busExMemoryStart;
   192:        XEiJ.busExMemoryArray[a    ] = (byte)  d;
   193:      }
   194:     @Override protected void mmdWw (int a, int d) throws M68kException {
   195:        a -= XEiJ.busExMemoryStart;
   196:        XEiJ.busExMemoryArray[a    ] = (byte) (d >> 8);
   197:        XEiJ.busExMemoryArray[a + 1] = (byte)  d;
   198:      }
   199:     @Override protected void mmdWl (int a, int d) throws M68kException {
   200:        a -= XEiJ.busExMemoryStart;
   201:        XEiJ.busExMemoryArray[a    ] = (byte) (d >> 24);
   202:        XEiJ.busExMemoryArray[a + 1] = (byte) (d >> 16);
   203:        XEiJ.busExMemoryArray[a + 2] = (byte) (d >> 8);
   204:        XEiJ.busExMemoryArray[a + 3] = (byte)  d;
   205:      }
   206:   },  //MMD_XMM
   207: 
   208:   //--------------------------------------------------------------------------------
   209:   //MMD_GE0 グラフィックス画面(512ドット16色ページ0)
   210:   //
   211:   //  512ドット16色
   212:   //                アドレス             アクセス                  格納
   213:   //    GE0  0x00c00000~0x00c7ffff  ............3210  ──  ............3210
   214:   //    GE1  0x00c80000~0x00cfffff  ............7654  ──  ............7654
   215:   //    GE2  0x00d00000~0x00d7ffff  ............ba98  ──  ............ba98
   216:   //    GE3  0x00d80000~0x00dfffff  ............fedc  ──  ............fedc
   217:   //
   218:   MMD_GE0 {
   219:     @Override public String toString () {
   220:       return Multilingual.mlnJapanese ? "グラフィックス画面 (512 ドット 16 色 ページ 0)" : "Graphics Screen (512 dots 16 colors page 0)";
   221:     }
   222:     //ピーク
   223:     @Override protected byte mmdPbs (int a) {
   224:       a &= XEiJ.BUS_MOTHER_MASK;
   225:       return MainMemory.mmrM8[a];
   226:     }
   227:     @Override protected int mmdPbz (int a) {
   228:       a &= XEiJ.BUS_MOTHER_MASK;
   229:       return MainMemory.mmrM8[a];
   230:     }
   231:     @Override protected int mmdPws (int a) {
   232:       a &= XEiJ.BUS_MOTHER_MASK;
   233:       return MainMemory.mmrM8[a + 1];
   234:     }
   235:     @Override protected int mmdPwz (int a) {
   236:       a &= XEiJ.BUS_MOTHER_MASK;
   237:       return MainMemory.mmrM8[a + 1];
   238:     }
   239:     @Override protected int mmdPls (int a) {
   240:       a &= XEiJ.BUS_MOTHER_MASK;
   241:       return MainMemory.mmrM8[a + 1] << 16 | MainMemory.mmrM8[a + 3];
   242:     }
   243:     //リード
   244:     @Override protected byte mmdRbs (int a) throws M68kException {
   245:        a &= XEiJ.BUS_MOTHER_MASK;
   246:        return MainMemory.mmrM8[a];
   247:      }
   248:     @Override protected int mmdRbz (int a) throws M68kException {
   249:        a &= XEiJ.BUS_MOTHER_MASK;
   250:        return MainMemory.mmrM8[a];
   251:      }
   252:     @Override protected int mmdRws (int a) throws M68kException {
   253:        a &= XEiJ.BUS_MOTHER_MASK;
   254:        return MainMemory.mmrM8[a + 1];
   255:      }
   256:     @Override protected int mmdRwz (int a) throws M68kException {
   257:        a &= XEiJ.BUS_MOTHER_MASK;
   258:        return MainMemory.mmrM8[a + 1];
   259:      }
   260:     @Override protected int mmdRls (int a) throws M68kException {
   261:        a &= XEiJ.BUS_MOTHER_MASK;
   262:        return MainMemory.mmrM8[a + 1] << 16 | MainMemory.mmrM8[a + 3];
   263:      }
   264:     //ライト
   265:     @Override protected void mmdWb (int a, int d) throws M68kException {
   266:        a &= XEiJ.BUS_MOTHER_MASK;
   267:        if (XEiJ.TEST_BIT_0_SHIFT ? a << 31 - 0 < 0 : (a & 1) != 0) {
   268:          MainMemory.mmrM8[a] = (byte) (d          & 15);
   269:          int y = (a >> 10) - CRTC.crtR13GrYCurr[0] & 511;
   270:          CRTC.crtRasterStamp[y      ] = 0;
   271:          CRTC.crtRasterStamp[y + 512] = 0;
   272:        }
   273:      }
   274:     @Override protected void mmdWw (int a, int d) throws M68kException {
   275:        a &= XEiJ.BUS_MOTHER_MASK;
   276:        MainMemory.mmrM8[a + 1] = (byte) (d          & 15);
   277:        int y = (a >> 10) - CRTC.crtR13GrYCurr[0] & 511;
   278:        CRTC.crtRasterStamp[y      ] = 0;
   279:        CRTC.crtRasterStamp[y + 512] = 0;
   280:      }
   281:     @Override protected void mmdWl (int a, int d) throws M68kException {
   282:        a &= XEiJ.BUS_MOTHER_MASK;
   283:        MainMemory.mmrM8[a + 1] = (byte) (d << 12  >>> 28);
   284:        MainMemory.mmrM8[a + 3] = (byte) (d          & 15);
   285:        int y = (a >> 10) - CRTC.crtR13GrYCurr[0] & 511;
   286:        CRTC.crtRasterStamp[y      ] = 0;
   287:        CRTC.crtRasterStamp[y + 512] = 0;
   288:      }
   289:   },  //MMD_GE0
   290: 
   291:   //--------------------------------------------------------------------------------
   292:   //MMD_GE1 グラフィックス画面(512ドット16色ページ1)
   293:   //
   294:   //  512ドット16色
   295:   //                アドレス             アクセス                  格納
   296:   //    GE0  0x00c00000~0x00c7ffff  ............3210  ──  ............3210
   297:   //    GE1  0x00c80000~0x00cfffff  ............7654  ──  ............7654
   298:   //    GE2  0x00d00000~0x00d7ffff  ............ba98  ──  ............ba98
   299:   //    GE3  0x00d80000~0x00dfffff  ............fedc  ──  ............fedc
   300:   //
   301:   MMD_GE1 {
   302:     @Override public String toString () {
   303:       return Multilingual.mlnJapanese ? "グラフィックス画面 (512 ドット 16 色 ページ 1)" : "Graphics Screen (512 dots 16 colors page 1)";
   304:     }
   305:     //ピーク
   306:     @Override protected byte mmdPbs (int a) {
   307:       a &= XEiJ.BUS_MOTHER_MASK;
   308:       return MainMemory.mmrM8[a];
   309:     }
   310:     @Override protected int mmdPbz (int a) {
   311:       a &= XEiJ.BUS_MOTHER_MASK;
   312:       return MainMemory.mmrM8[a];
   313:     }
   314:     @Override protected int mmdPws (int a) {
   315:       a &= XEiJ.BUS_MOTHER_MASK;
   316:       return MainMemory.mmrM8[a + 1];
   317:     }
   318:     @Override protected int mmdPwz (int a) {
   319:       a &= XEiJ.BUS_MOTHER_MASK;
   320:       return MainMemory.mmrM8[a + 1];
   321:     }
   322:     @Override protected int mmdPls (int a) {
   323:       a &= XEiJ.BUS_MOTHER_MASK;
   324:       return MainMemory.mmrM8[a + 1] << 16 | MainMemory.mmrM8[a + 3];
   325:     }
   326:     //リード
   327:     @Override protected byte mmdRbs (int a) throws M68kException {
   328:       a &= XEiJ.BUS_MOTHER_MASK;
   329:        return MainMemory.mmrM8[a];
   330:      }
   331:     @Override protected int mmdRbz (int a) throws M68kException {
   332:       a &= XEiJ.BUS_MOTHER_MASK;
   333:        return MainMemory.mmrM8[a];
   334:      }
   335:     @Override protected int mmdRws (int a) throws M68kException {
   336:       a &= XEiJ.BUS_MOTHER_MASK;
   337:        return MainMemory.mmrM8[a + 1];
   338:      }
   339:     @Override protected int mmdRwz (int a) throws M68kException {
   340:       a &= XEiJ.BUS_MOTHER_MASK;
   341:        return MainMemory.mmrM8[a + 1];
   342:      }
   343:     @Override protected int mmdRls (int a) throws M68kException {
   344:        a &= XEiJ.BUS_MOTHER_MASK;
   345:        return MainMemory.mmrM8[a + 1] << 16 | MainMemory.mmrM8[a + 3];
   346:      }
   347:     //ライト
   348:     @Override protected void mmdWb (int a, int d) throws M68kException {
   349:        a &= XEiJ.BUS_MOTHER_MASK;
   350:        if (XEiJ.TEST_BIT_0_SHIFT ? a << 31 - 0 < 0 : (a & 1) != 0) {
   351:          MainMemory.mmrM8[a] = (byte) (d          & 15);
   352:          int y = (a >> 10) - CRTC.crtR13GrYCurr[1] & 511;
   353:          CRTC.crtRasterStamp[y      ] = 0;
   354:          CRTC.crtRasterStamp[y + 512] = 0;
   355:        }
   356:      }
   357:     @Override protected void mmdWw (int a, int d) throws M68kException {
   358:        a &= XEiJ.BUS_MOTHER_MASK;
   359:        MainMemory.mmrM8[a + 1] = (byte) (d          & 15);
   360:        int y = (a >> 10) - CRTC.crtR13GrYCurr[1] & 511;
   361:        CRTC.crtRasterStamp[y      ] = 0;
   362:        CRTC.crtRasterStamp[y + 512] = 0;
   363:      }
   364:     @Override protected void mmdWl (int a, int d) throws M68kException {
   365:        a &= XEiJ.BUS_MOTHER_MASK;
   366:        MainMemory.mmrM8[a + 1] = (byte) (d << 12  >>> 28);
   367:        MainMemory.mmrM8[a + 3] = (byte) (d          & 15);
   368:        int y = (a >> 10) - CRTC.crtR13GrYCurr[1] & 511;
   369:        CRTC.crtRasterStamp[y      ] = 0;
   370:        CRTC.crtRasterStamp[y + 512] = 0;
   371:      }
   372:   },  //MMD_GE1
   373: 
   374:   //--------------------------------------------------------------------------------
   375:   //MMD_GE2 グラフィックス画面(512ドット16色ページ2)
   376:   //
   377:   //  512ドット16色
   378:   //                アドレス             アクセス                  格納
   379:   //    GE0  0x00c00000~0x00c7ffff  ............3210  ──  ............3210
   380:   //    GE1  0x00c80000~0x00cfffff  ............7654  ──  ............7654
   381:   //    GE2  0x00d00000~0x00d7ffff  ............ba98  ──  ............ba98
   382:   //    GE3  0x00d80000~0x00dfffff  ............fedc  ──  ............fedc
   383:   //
   384:   MMD_GE2 {
   385:     @Override public String toString () {
   386:       return Multilingual.mlnJapanese ? "グラフィックス画面 (512 ドット 16 色 ページ 2)" : "Graphics Screen (512 dots 16 colors page 2)";
   387:     }
   388:     //ピーク
   389:     @Override protected byte mmdPbs (int a) {
   390:       a &= XEiJ.BUS_MOTHER_MASK;
   391:       return MainMemory.mmrM8[a];
   392:     }
   393:     @Override protected int mmdPbz (int a) {
   394:       a &= XEiJ.BUS_MOTHER_MASK;
   395:       return MainMemory.mmrM8[a];
   396:     }
   397:     @Override protected int mmdPws (int a) {
   398:       a &= XEiJ.BUS_MOTHER_MASK;
   399:       return MainMemory.mmrM8[a + 1];
   400:     }
   401:     @Override protected int mmdPwz (int a) {
   402:       a &= XEiJ.BUS_MOTHER_MASK;
   403:       return MainMemory.mmrM8[a + 1];
   404:     }
   405:     @Override protected int mmdPls (int a) {
   406:       a &= XEiJ.BUS_MOTHER_MASK;
   407:       return MainMemory.mmrM8[a + 1] << 16 | MainMemory.mmrM8[a + 3];
   408:     }
   409:     //リード
   410:     @Override protected byte mmdRbs (int a) throws M68kException {
   411:        a &= XEiJ.BUS_MOTHER_MASK;
   412:        return MainMemory.mmrM8[a];
   413:      }
   414:     @Override protected int mmdRbz (int a) throws M68kException {
   415:        a &= XEiJ.BUS_MOTHER_MASK;
   416:        return MainMemory.mmrM8[a];
   417:      }
   418:     @Override protected int mmdRws (int a) throws M68kException {
   419:        a &= XEiJ.BUS_MOTHER_MASK;
   420:        return MainMemory.mmrM8[a + 1];
   421:      }
   422:     @Override protected int mmdRwz (int a) throws M68kException {
   423:        a &= XEiJ.BUS_MOTHER_MASK;
   424:        return MainMemory.mmrM8[a + 1];
   425:      }
   426:     @Override protected int mmdRls (int a) throws M68kException {
   427:        a &= XEiJ.BUS_MOTHER_MASK;
   428:        return MainMemory.mmrM8[a + 1] << 16 | MainMemory.mmrM8[a + 3];
   429:      }
   430:     //ライト
   431:     @Override protected void mmdWb (int a, int d) throws M68kException {
   432:        a &= XEiJ.BUS_MOTHER_MASK;
   433:        if (XEiJ.TEST_BIT_0_SHIFT ? a << 31 - 0 < 0 : (a & 1) != 0) {
   434:          MainMemory.mmrM8[a] = (byte) (d          & 15);
   435:          int y = (a >> 10) - CRTC.crtR13GrYCurr[2] & 511;
   436:          CRTC.crtRasterStamp[y      ] = 0;
   437:          CRTC.crtRasterStamp[y + 512] = 0;
   438:        }
   439:      }
   440:     @Override protected void mmdWw (int a, int d) throws M68kException {
   441:        a &= XEiJ.BUS_MOTHER_MASK;
   442:        MainMemory.mmrM8[a + 1] = (byte) (d          & 15);
   443:        int y = (a >> 10) - CRTC.crtR13GrYCurr[2] & 511;
   444:        CRTC.crtRasterStamp[y      ] = 0;
   445:        CRTC.crtRasterStamp[y + 512] = 0;
   446:      }
   447:     @Override protected void mmdWl (int a, int d) throws M68kException {
   448:        a &= XEiJ.BUS_MOTHER_MASK;
   449:        MainMemory.mmrM8[a + 1] = (byte) (d << 12  >>> 28);
   450:        MainMemory.mmrM8[a + 3] = (byte) (d          & 15);
   451:        int y = (a >> 10) - CRTC.crtR13GrYCurr[2] & 511;
   452:        CRTC.crtRasterStamp[y      ] = 0;
   453:        CRTC.crtRasterStamp[y + 512] = 0;
   454:      }
   455:   },  //MMD_GE2
   456: 
   457:   //--------------------------------------------------------------------------------
   458:   //MMD_GE3 グラフィックス画面(512ドット16色ページ3)
   459:   //
   460:   //  512ドット16色
   461:   //                アドレス             アクセス                  格納
   462:   //    GE0  0x00c00000~0x00c7ffff  ............3210  ──  ............3210
   463:   //    GE1  0x00c80000~0x00cfffff  ............7654  ──  ............7654
   464:   //    GE2  0x00d00000~0x00d7ffff  ............ba98  ──  ............ba98
   465:   //    GE3  0x00d80000~0x00dfffff  ............fedc  ──  ............fedc
   466:   //
   467:   MMD_GE3 {
   468:     @Override public String toString () {
   469:       return Multilingual.mlnJapanese ? "グラフィックス画面 (512 ドット 16 色 ページ 3)" : "Graphics Screen (512 dots 16 colors page 3)";
   470:     }
   471:     //ピーク
   472:     @Override protected byte mmdPbs (int a) {
   473:       a &= XEiJ.BUS_MOTHER_MASK;
   474:       return MainMemory.mmrM8[a];
   475:     }
   476:     @Override protected int mmdPbz (int a) {
   477:       a &= XEiJ.BUS_MOTHER_MASK;
   478:       return MainMemory.mmrM8[a];
   479:     }
   480:     @Override protected int mmdPws (int a) {
   481:       a &= XEiJ.BUS_MOTHER_MASK;
   482:       return MainMemory.mmrM8[a + 1];
   483:     }
   484:     @Override protected int mmdPwz (int a) {
   485:       a &= XEiJ.BUS_MOTHER_MASK;
   486:       return MainMemory.mmrM8[a + 1];
   487:     }
   488:     @Override protected int mmdPls (int a) {
   489:       a &= XEiJ.BUS_MOTHER_MASK;
   490:       return MainMemory.mmrM8[a + 1] << 16 | MainMemory.mmrM8[a + 3];
   491:     }
   492:     //リード
   493:     @Override protected byte mmdRbs (int a) throws M68kException {
   494:        a &= XEiJ.BUS_MOTHER_MASK;
   495:        return MainMemory.mmrM8[a];
   496:      }
   497:     @Override protected int mmdRbz (int a) throws M68kException {
   498:        a &= XEiJ.BUS_MOTHER_MASK;
   499:        return MainMemory.mmrM8[a];
   500:      }
   501:     @Override protected int mmdRws (int a) throws M68kException {
   502:        a &= XEiJ.BUS_MOTHER_MASK;
   503:        return MainMemory.mmrM8[a + 1];
   504:      }
   505:     @Override protected int mmdRwz (int a) throws M68kException {
   506:        a &= XEiJ.BUS_MOTHER_MASK;
   507:        return MainMemory.mmrM8[a + 1];
   508:      }
   509:     @Override protected int mmdRls (int a) throws M68kException {
   510:        a &= XEiJ.BUS_MOTHER_MASK;
   511:        return MainMemory.mmrM8[a + 1] << 16 | MainMemory.mmrM8[a + 3];
   512:      }
   513:     //ライト
   514:     @Override protected void mmdWb (int a, int d) throws M68kException {
   515:        a &= XEiJ.BUS_MOTHER_MASK;
   516:        if (XEiJ.TEST_BIT_0_SHIFT ? a << 31 - 0 < 0 : (a & 1) != 0) {
   517:          MainMemory.mmrM8[a] = (byte) (d          & 15);
   518:          int y = (a >> 10) - CRTC.crtR13GrYCurr[3] & 511;
   519:          CRTC.crtRasterStamp[y      ] = 0;
   520:          CRTC.crtRasterStamp[y + 512] = 0;
   521:        }
   522:      }
   523:     @Override protected void mmdWw (int a, int d) throws M68kException {
   524:        a &= XEiJ.BUS_MOTHER_MASK;
   525:        MainMemory.mmrM8[a + 1] = (byte) (d          & 15);
   526:        int y = (a >> 10) - CRTC.crtR13GrYCurr[3] & 511;
   527:        CRTC.crtRasterStamp[y      ] = 0;
   528:        CRTC.crtRasterStamp[y + 512] = 0;
   529:      }
   530:     @Override protected void mmdWl (int a, int d) throws M68kException {
   531:        a &= XEiJ.BUS_MOTHER_MASK;
   532:        MainMemory.mmrM8[a + 1] = (byte) (d << 12  >>> 28);
   533:        MainMemory.mmrM8[a + 3] = (byte) (d          & 15);
   534:        int y = (a >> 10) - CRTC.crtR13GrYCurr[3] & 511;
   535:        CRTC.crtRasterStamp[y      ] = 0;
   536:        CRTC.crtRasterStamp[y + 512] = 0;
   537:      }
   538:   },  //MMD_GE3
   539: 
   540:   //--------------------------------------------------------------------------------
   541:   //MMD_GF0 グラフィックス画面(512ドット256色ページ0)
   542:   //
   543:   //  512ドット256色
   544:   //                アドレス             アクセス                  格納
   545:   //    GF0  0x00c00000~0x00c7ffff  ........76543210  ─┬  ............3210
   546:   //    GF1  0x00c80000~0x00cfffff  ........fedcba98  ┐└  ............7654
   547:   //         0x00d00000~0x00d7ffff                    ├─  ............ba98
   548:   //         0x00d80000~0x00dfffff                    └─  ............fedc
   549:   //
   550:   MMD_GF0 {
   551:     @Override public String toString () {
   552:       return Multilingual.mlnJapanese ? "グラフィックス画面 (512 ドット 256 色 ページ 0)" : "Graphics Screen (512 dots 256 colors page 0)";
   553:     }
   554:     //ピーク
   555:     @Override protected byte mmdPbs (int a) {
   556:       a &= XEiJ.BUS_MOTHER_MASK;
   557:       return (byte) (MainMemory.mmrM8[a + 0x00080000] << 4 | MainMemory.mmrM8[a]);
   558:     }
   559:     @Override protected int mmdPbz (int a) {
   560:       a &= XEiJ.BUS_MOTHER_MASK;
   561:       return MainMemory.mmrM8[a + 0x00080000] << 4 | MainMemory.mmrM8[a];
   562:     }
   563:     @Override protected int mmdPws (int a) {
   564:       a &= XEiJ.BUS_MOTHER_MASK;
   565:       return MainMemory.mmrM8[a + 0x00080001] << 4 | MainMemory.mmrM8[a + 1];
   566:     }
   567:     @Override protected int mmdPwz (int a) {
   568:       a &= XEiJ.BUS_MOTHER_MASK;
   569:       return MainMemory.mmrM8[a + 0x00080001] << 4 | MainMemory.mmrM8[a + 1];
   570:     }
   571:     @Override protected int mmdPls (int a) {
   572:       a &= XEiJ.BUS_MOTHER_MASK;
   573:       return MainMemory.mmrM8[a + 0x00080001] << 20 | MainMemory.mmrM8[a + 1] << 16 | MainMemory.mmrM8[a + 0x00080003] << 4 | MainMemory.mmrM8[a + 3];
   574:     }
   575:     //リード
   576:     @Override protected byte mmdRbs (int a) throws M68kException {
   577:        a &= XEiJ.BUS_MOTHER_MASK;
   578:        return (byte) (MainMemory.mmrM8[a + 0x00080000] << 4 | MainMemory.mmrM8[a]);
   579:      }
   580:     @Override protected int mmdRbz (int a) throws M68kException {
   581:        a &= XEiJ.BUS_MOTHER_MASK;
   582:        return MainMemory.mmrM8[a + 0x00080000] << 4 | MainMemory.mmrM8[a];
   583:      }
   584:     @Override protected int mmdRws (int a) throws M68kException {
   585:        a &= XEiJ.BUS_MOTHER_MASK;
   586:        return MainMemory.mmrM8[a + 0x00080001] << 4 | MainMemory.mmrM8[a + 1];
   587:      }
   588:     @Override protected int mmdRwz (int a) throws M68kException {
   589:        a &= XEiJ.BUS_MOTHER_MASK;
   590:        return MainMemory.mmrM8[a + 0x00080001] << 4 | MainMemory.mmrM8[a + 1];
   591:      }
   592:     @Override protected int mmdRls (int a) throws M68kException {
   593:        a &= XEiJ.BUS_MOTHER_MASK;
   594:        return MainMemory.mmrM8[a + 0x00080001] << 20 | MainMemory.mmrM8[a + 1] << 16 | MainMemory.mmrM8[a + 0x00080003] << 4 | MainMemory.mmrM8[a + 3];
   595:      }
   596:     //ライト
   597:     @Override protected void mmdWb (int a, int d) throws M68kException {
   598:        a &= XEiJ.BUS_MOTHER_MASK;
   599:        if (XEiJ.TEST_BIT_0_SHIFT ? a << 31 - 0 < 0 : (a & 1) != 0) {
   600:          MainMemory.mmrM8[a + 0x00080000] = (byte) (d << 24  >>> 28);
   601:          MainMemory.mmrM8[a             ] = (byte) (d          & 15);
   602:          a >>= 10;
   603:          int y = a - CRTC.crtR13GrYCurr[0] & 511;
   604:          CRTC.crtRasterStamp[y      ] = 0;
   605:          CRTC.crtRasterStamp[y + 512] = 0;
   606:          y = a - CRTC.crtR13GrYCurr[1] & 511;
   607:          CRTC.crtRasterStamp[y      ] = 0;
   608:          CRTC.crtRasterStamp[y + 512] = 0;
   609:        }
   610:      }
   611:     @Override protected void mmdWw (int a, int d) throws M68kException {
   612:        a &= XEiJ.BUS_MOTHER_MASK;
   613:        MainMemory.mmrM8[a + 0x00080001] = (byte) (d << 24  >>> 28);
   614:        MainMemory.mmrM8[a + 0x00000001] = (byte) (d          & 15);
   615:        a >>= 10;
   616:        int y = a - CRTC.crtR13GrYCurr[0] & 511;
   617:        CRTC.crtRasterStamp[y      ] = 0;
   618:        CRTC.crtRasterStamp[y + 512] = 0;
   619:        y = a - CRTC.crtR13GrYCurr[1] & 511;
   620:        CRTC.crtRasterStamp[y      ] = 0;
   621:        CRTC.crtRasterStamp[y + 512] = 0;
   622:      }
   623:     @Override protected void mmdWl (int a, int d) throws M68kException {
   624:        a &= XEiJ.BUS_MOTHER_MASK;
   625:        MainMemory.mmrM8[a + 0x00080001] = (byte) (d <<  8  >>> 28);
   626:        MainMemory.mmrM8[a + 0x00000001] = (byte) (d << 12  >>> 28);
   627:        MainMemory.mmrM8[a + 0x00080003] = (byte) (d << 24  >>> 28);
   628:        MainMemory.mmrM8[a + 0x00000003] = (byte) (d          & 15);
   629:        a >>= 10;
   630:        int y = a - CRTC.crtR13GrYCurr[0] & 511;
   631:        CRTC.crtRasterStamp[y      ] = 0;
   632:        CRTC.crtRasterStamp[y + 512] = 0;
   633:        y = a - CRTC.crtR13GrYCurr[1] & 511;
   634:        CRTC.crtRasterStamp[y      ] = 0;
   635:        CRTC.crtRasterStamp[y + 512] = 0;
   636:      }
   637:   },  //MMD_GF0
   638: 
   639:   //--------------------------------------------------------------------------------
   640:   //MMD_GF1 グラフィックス画面(512ドット256色ページ1)
   641:   //
   642:   //  512ドット256色
   643:   //                アドレス             アクセス                  格納
   644:   //    GF0  0x00c00000~0x00c7ffff  ........76543210  ─┬  ............3210
   645:   //    GF1  0x00c80000~0x00cfffff  ........fedcba98  ┐└  ............7654
   646:   //         0x00d00000~0x00d7ffff                    ├─  ............ba98
   647:   //         0x00d80000~0x00dfffff                    └─  ............fedc
   648:   //
   649:   MMD_GF1 {
   650:     @Override public String toString () {
   651:       return Multilingual.mlnJapanese ? "グラフィックス画面 (512 ドット 256 色 ページ 1)" : "Graphics Screen (512 dots 256 colors page 1)";
   652:     }
   653:     //ピーク
   654:     @Override protected byte mmdPbs (int a) {
   655:       a &= XEiJ.BUS_MOTHER_MASK;
   656:       return (byte) (MainMemory.mmrM8[a + 0x00100000] << 4 | MainMemory.mmrM8[a + 0x00080000]);
   657:     }
   658:     @Override protected int mmdPbz (int a) {
   659:       a &= XEiJ.BUS_MOTHER_MASK;
   660:       return MainMemory.mmrM8[a + 0x00100000] << 4 | MainMemory.mmrM8[a + 0x00080000];
   661:     }
   662:     @Override protected int mmdPws (int a) {
   663:       a &= XEiJ.BUS_MOTHER_MASK;
   664:       return MainMemory.mmrM8[a + 0x00100001] << 4 | MainMemory.mmrM8[a + 0x00080001];
   665:     }
   666:     @Override protected int mmdPwz (int a) {
   667:       a &= XEiJ.BUS_MOTHER_MASK;
   668:       return MainMemory.mmrM8[a + 0x00100001] << 4 | MainMemory.mmrM8[a + 0x00080001];
   669:     }
   670:     @Override protected int mmdPls (int a) {
   671:       a &= XEiJ.BUS_MOTHER_MASK;
   672:       return MainMemory.mmrM8[a + 0x00100001] << 20 | MainMemory.mmrM8[a + 0x00080001] << 16 | MainMemory.mmrM8[a + 0x00100003] << 4 | MainMemory.mmrM8[a + 0x00080003];
   673:     }
   674:     //リード
   675:     @Override protected byte mmdRbs (int a) throws M68kException {
   676:        a &= XEiJ.BUS_MOTHER_MASK;
   677:        return (byte) (MainMemory.mmrM8[a + 0x00100000] << 4 | MainMemory.mmrM8[a + 0x00080000]);
   678:      }
   679:     @Override protected int mmdRbz (int a) throws M68kException {
   680:        a &= XEiJ.BUS_MOTHER_MASK;
   681:        return MainMemory.mmrM8[a + 0x00100000] << 4 | MainMemory.mmrM8[a + 0x00080000];
   682:      }
   683:     @Override protected int mmdRws (int a) throws M68kException {
   684:        a &= XEiJ.BUS_MOTHER_MASK;
   685:        return MainMemory.mmrM8[a + 0x00100001] << 4 | MainMemory.mmrM8[a + 0x00080001];
   686:      }
   687:     @Override protected int mmdRwz (int a) throws M68kException {
   688:        a &= XEiJ.BUS_MOTHER_MASK;
   689:        return MainMemory.mmrM8[a + 0x00100001] << 4 | MainMemory.mmrM8[a + 0x00080001];
   690:      }
   691:     @Override protected int mmdRls (int a) throws M68kException {
   692:        a &= XEiJ.BUS_MOTHER_MASK;
   693:        return MainMemory.mmrM8[a + 0x00100001] << 20 | MainMemory.mmrM8[a + 0x00080001] << 16 | MainMemory.mmrM8[a + 0x00100003] << 4 | MainMemory.mmrM8[a + 0x00080003];
   694:      }
   695:     //ライト
   696:     @Override protected void mmdWb (int a, int d) throws M68kException {
   697:        a &= XEiJ.BUS_MOTHER_MASK;
   698:        if (XEiJ.TEST_BIT_0_SHIFT ? a << 31 - 0 < 0 : (a & 1) != 0) {
   699:          MainMemory.mmrM8[a + 0x00100000] = (byte) (d << 24  >>> 28);
   700:          MainMemory.mmrM8[a + 0x00080000] = (byte) (d          & 15);
   701:          a >>= 10;
   702:          int y = a - CRTC.crtR13GrYCurr[2] & 511;
   703:          CRTC.crtRasterStamp[y      ] = 0;
   704:          CRTC.crtRasterStamp[y + 512] = 0;
   705:          y = a - CRTC.crtR13GrYCurr[3] & 511;
   706:          CRTC.crtRasterStamp[y      ] = 0;
   707:          CRTC.crtRasterStamp[y + 512] = 0;
   708:        }
   709:      }
   710:     @Override protected void mmdWw (int a, int d) throws M68kException {
   711:        a &= XEiJ.BUS_MOTHER_MASK;
   712:        MainMemory.mmrM8[a + 0x00100001] = (byte) (d << 24  >>> 28);
   713:        MainMemory.mmrM8[a + 0x00080001] = (byte) (d          & 15);
   714:        a >>= 10;
   715:        int y = a - CRTC.crtR13GrYCurr[2] & 511;
   716:        CRTC.crtRasterStamp[y      ] = 0;
   717:        CRTC.crtRasterStamp[y + 512] = 0;
   718:        y = a - CRTC.crtR13GrYCurr[3] & 511;
   719:        CRTC.crtRasterStamp[y      ] = 0;
   720:        CRTC.crtRasterStamp[y + 512] = 0;
   721:      }
   722:     @Override protected void mmdWl (int a, int d) throws M68kException {
   723:        a &= XEiJ.BUS_MOTHER_MASK;
   724:        MainMemory.mmrM8[a + 0x00100001] = (byte) (d <<  8  >>> 28);
   725:        MainMemory.mmrM8[a + 0x00080001] = (byte) (d << 12  >>> 28);
   726:        MainMemory.mmrM8[a + 0x00100003] = (byte) (d << 24  >>> 28);
   727:        MainMemory.mmrM8[a + 0x00080003] = (byte) (d          & 15);
   728:        a >>= 10;
   729:        int y = a - CRTC.crtR13GrYCurr[2] & 511;
   730:        CRTC.crtRasterStamp[y      ] = 0;
   731:        CRTC.crtRasterStamp[y + 512] = 0;
   732:        y = a - CRTC.crtR13GrYCurr[3] & 511;
   733:        CRTC.crtRasterStamp[y      ] = 0;
   734:        CRTC.crtRasterStamp[y + 512] = 0;
   735:      }
   736:   },  //MMD_GF1
   737: 
   738:   //--------------------------------------------------------------------------------
   739:   //MMD_GM2 グラフィックス画面(メモリモード2)
   740:   //
   741:   //  バイトリード
   742:   //    0x00c00000  0x00が読み出される
   743:   //    0x00c00001  4bitページ1-0が読み出される
   744:   //    0x00c80000  0x00が読み出される
   745:   //    0x00c80001  0x00が読み出される
   746:   //    0x00d00000  0x00が読み出される
   747:   //    0x00d00001  4bitページ1-0が読み出される
   748:   //    0x00d80000  0x00が読み出される
   749:   //    0x00d80001  0x00が読み出される
   750:   //
   751:   //  ワードリード
   752:   //    0x00c00000  上位バイトは0x00で下位バイトに4bitページ1-0が読み出される
   753:   //    0x00c80000  上位バイトは0x00で下位バイトに4bitページ3-2が読み出される
   754:   //    0x00d00000  上位バイトは0x00で下位バイトに4bitページ1-0が読み出される
   755:   //    0x00d80000  上位バイトは0x00で下位バイトに4bitページ3-2が読み出される
   756:   //
   757:   //  バイトライト
   758:   //    0x00c00000  060turboの060モードのときデータは無視され0x00が4bitページ3-2に書き込まれる。それ以外はデータが4bitページ3-2に書き込まれる
   759:   //    0x00c00001  データが4bitページ1-0に書き込まれる
   760:   //    0x00c80000  060turboの060モードのときデータは無視され0x00が4bitページ3-2に書き込まれる。それ以外はデータが4bitページ3-2に書き込まれる
   761:   //    0x00c80001  データが4bitページ1-0に書き込まれる
   762:   //    0x00d00000  060turboの060モードのときデータは無視され0x00が4bitページ3-2に書き込まれる。それ以外はデータが4bitページ3-2に書き込まれる
   763:   //    0x00d00001  データが4bitページ1-0に書き込まれる
   764:   //    0x00d80000  060turboの060モードのときデータは無視され0x00が4bitページ3-2に書き込まれる。それ以外はデータが4bitページ3-2に書き込まれる
   765:   //    0x00d80001  データが4bitページ1-0に書き込まれる
   766:   //
   767:   //  ワードライト
   768:   //    0x00c00000  上位バイトは無視され下位バイトが4bitページ3-2と4bitページ1-0の両方に書き込まれる
   769:   //    0x00c80000  上位バイトは無視され下位バイトが4bitページ3-2と4bitページ1-0の両方に書き込まれる
   770:   //    0x00d00000  上位バイトは無視され下位バイトが4bitページ3-2と4bitページ1-0の両方に書き込まれる
   771:   //    0x00d80000  上位バイトは無視され下位バイトが4bitページ3-2と4bitページ1-0の両方に書き込まれる
   772:   //
   773:   MMD_GM2 {
   774:     @Override public String toString () {
   775:       return Multilingual.mlnJapanese ? "グラフィックス画面 (メモリモード 2)" : "Graphics Screen (memory mode 2)";
   776:     }
   777:     //ピーク
   778:     @Override protected byte mmdPbs (int a) {
   779:       if ((a & 0x00080001) == 0x00000001) {  //0x00c00000..0x00c7ffff,0x00d00000..0x00d7ffffかつ下位バイト
   780:         a &= 0x00c7fffe;
   781:         return (byte) (MainMemory.mmrM8[0x00080001 + a] << 4 |  //4bitページ1
   782:                        MainMemory.mmrM8[0x00000001 + a]);  //4bitページ0
   783:       } else {  //0x00c80000..0x00cfffff,0x00d80000..0x00dfffffまたは上位バイト
   784:         return 0x00;
   785:       }
   786:     }
   787:     @Override protected int mmdPbz (int a) {
   788:       if ((a & 0x00080001) == 0x00000001) {  //0x00c00000..0x00c7ffff,0x00d00000..0x00d7ffffかつ下位バイト
   789:         a &= 0x00c7fffe;
   790:         return (byte) (MainMemory.mmrM8[0x00080001 + a] << 4 |  //4bitページ1
   791:                        MainMemory.mmrM8[0x00000001 + a]);  //4bitページ0
   792:       } else {  //0x00c80000..0x00cfffff,0x00d80000..0x00dfffffまたは上位バイト
   793:         return 0x00;
   794:       }
   795:     }
   796:     @Override protected int mmdPws (int a) {
   797:       if ((a & 0x00080000) == 0x00000000) {  //0x00c00000..0x00c7ffff,0x00d00000..0x00d7ffff
   798:         a &= 0x00c7fffe;
   799:         return (MainMemory.mmrM8[0x00080001 + a] << 4 |  //4bitページ1
   800:                 MainMemory.mmrM8[0x00000001 + a]);  //4bitページ0
   801:       } else {  //0x00c80000..0x00cfffff,0x00d80000..0x00dfffff
   802:         a &= 0x00c7fffe;
   803:         return (MainMemory.mmrM8[0x00180001 + a] << 4 |  //4bitページ3
   804:                 MainMemory.mmrM8[0x00100001 + a]);  //4bitページ2
   805:       }
   806:     }
   807:     @Override protected int mmdPwz (int a) {
   808:       if ((a & 0x00080000) == 0x00000000) {  //0x00c00000..0x00c7ffff,0x00d00000..0x00d7ffff
   809:         a &= 0x00c7fffe;
   810:         return (MainMemory.mmrM8[0x00080001 + a] << 4 |  //4bitページ1
   811:                 MainMemory.mmrM8[0x00000001 + a]);  //4bitページ0
   812:       } else {  //0x00c80000..0x00cfffff,0x00d80000..0x00dfffff
   813:         a &= 0x00c7fffe;
   814:         return (MainMemory.mmrM8[0x00180001 + a] << 4 |  //4bitページ3
   815:                 MainMemory.mmrM8[0x00100001 + a]);  //4bitページ2
   816:       }
   817:     }
   818:     @Override protected int mmdPls (int a) {
   819:       a &= 0x00d7fffe;
   820:       return (MainMemory.mmrM8[0x00080001 + a] << 20 |  //4bitページ1,3
   821:               MainMemory.mmrM8[0x00000001 + a] << 16 |  //4bitページ0,2
   822:               MainMemory.mmrM8[0x00080003 + a] <<  4 |  //4bitページ1,3
   823:               MainMemory.mmrM8[0x00000003 + a]);  //4bitページ0,2
   824:     }
   825:     //リード
   826:     @Override protected byte mmdRbs (int a) throws M68kException {
   827:        if ((a & 0x00080001) == 0x00000001) {  //0x00c00000..0x00c7ffff,0x00d00000..0x00d7ffffかつ下位バイト
   828:          a &= 0x00c7fffe;
   829:          return (byte) (MainMemory.mmrM8[0x00080001 + a] << 4 |  //4bitページ1
   830:                         MainMemory.mmrM8[0x00000001 + a]);  //4bitページ0
   831:        } else {  //0x00c80000..0x00cfffff,0x00d80000..0x00dfffffまたは上位バイト
   832:          return 0x00;
   833:        }
   834:      }
   835:     @Override protected int mmdRbz (int a) throws M68kException {
   836:        if ((a & 0x00080001) == 0x00000001) {  //0x00c00000..0x00c7ffff,0x00d00000..0x00d7ffffかつ下位バイト
   837:          a &= 0x00c7fffe;
   838:          return (byte) (MainMemory.mmrM8[0x00080001 + a] << 4 |  //4bitページ1
   839:                         MainMemory.mmrM8[0x00000001 + a]);  //4bitページ0
   840:        } else {  //0x00c80000..0x00cfffff,0x00d80000..0x00dfffffまたは上位バイト
   841:          return 0x00;
   842:        }
   843:      }
   844:     @Override protected int mmdRws (int a) throws M68kException {
   845:        if ((a & 0x00080000) == 0x00000000) {  //0x00c00000..0x00c7ffff,0x00d00000..0x00d7ffff
   846:          a &= 0x00c7fffe;
   847:          return (MainMemory.mmrM8[0x00080001 + a] << 4 |  //4bitページ1
   848:                  MainMemory.mmrM8[0x00000001 + a]);  //4bitページ0
   849:        } else {  //0x00c80000..0x00cfffff,0x00d80000..0x00dfffff
   850:          a &= 0x00c7fffe;
   851:          return (MainMemory.mmrM8[0x00180001 + a] << 4 |  //4bitページ3
   852:                  MainMemory.mmrM8[0x00100001 + a]);  //4bitページ2
   853:        }
   854:      }
   855:     @Override protected int mmdRwz (int a) throws M68kException {
   856:        if ((a & 0x00080000) == 0x00000000) {  //0x00c00000..0x00c7ffff,0x00d00000..0x00d7ffff
   857:          a &= 0x00c7fffe;
   858:          return (MainMemory.mmrM8[0x00080001 + a] << 4 |  //4bitページ1
   859:                  MainMemory.mmrM8[0x00000001 + a]);  //4bitページ0
   860:        } else {  //0x00c80000..0x00cfffff,0x00d80000..0x00dfffff
   861:          a &= 0x00c7fffe;
   862:          return (MainMemory.mmrM8[0x00180001 + a] << 4 |  //4bitページ3
   863:                  MainMemory.mmrM8[0x00100001 + a]);  //4bitページ2
   864:        }
   865:      }
   866:     @Override protected int mmdRls (int a) throws M68kException {
   867:        a &= 0x00d7fffe;
   868:        return (MainMemory.mmrM8[0x00080001 + a] << 20 |  //4bitページ1,3
   869:                MainMemory.mmrM8[0x00000001 + a] << 16 |  //4bitページ0,2
   870:                MainMemory.mmrM8[0x00080003 + a] <<  4 |  //4bitページ1,3
   871:                MainMemory.mmrM8[0x00000003 + a]);  //4bitページ0,2
   872:      }
   873:     //ライト
   874:     @Override protected void mmdWb (int a, int d) throws M68kException {
   875:        if ((a & 0x00000001) == 0x00000000) {  //上位バイト
   876:          a &= 0x00c7fffe;
   877:          if (XEiJ.mpuCoreType == 6) {
   878:            MainMemory.mmrM8[0x00180001 + a] = 0;  //4bitページ3
   879:            MainMemory.mmrM8[0x00100001 + a] = 0;  //4bitページ2
   880:          } else {
   881:            MainMemory.mmrM8[0x00180001 + a] = (byte) (d >>> 4 & 15);  //4bitページ3
   882:            MainMemory.mmrM8[0x00100001 + a] = (byte) (d       & 15);  //4bitページ2
   883:          }
   884:          a >>>= 10;
   885:          int y = a - CRTC.crtR13GrYCurr[3] & 511;
   886:          CRTC.crtRasterStamp[y      ] = 0;
   887:          CRTC.crtRasterStamp[y + 512] = 0;
   888:          y = a - CRTC.crtR13GrYCurr[2] & 511;
   889:          CRTC.crtRasterStamp[y      ] = 0;
   890:          CRTC.crtRasterStamp[y + 512] = 0;
   891:        } else {  //下位バイト
   892:          a &= 0x00c7fffe;
   893:          MainMemory.mmrM8[0x00080001 + a] = (byte) (d >>> 4 & 15);  //4bitページ1
   894:          MainMemory.mmrM8[0x00000001 + a] = (byte) (d       & 15);  //4bitページ0
   895:          a >>>= 10;
   896:          int y = a - CRTC.crtR13GrYCurr[1] & 511;
   897:          CRTC.crtRasterStamp[y      ] = 0;
   898:          CRTC.crtRasterStamp[y + 512] = 0;
   899:          y = a - CRTC.crtR13GrYCurr[0] & 511;
   900:          CRTC.crtRasterStamp[y      ] = 0;
   901:          CRTC.crtRasterStamp[y + 512] = 0;
   902:        }
   903:      }
   904:     @Override protected void mmdWw (int a, int d) throws M68kException {
   905:        a &= 0x00c7fffe;
   906:        MainMemory.mmrM8[0x00180001 + a] = MainMemory.mmrM8[0x00080001 + a] = (byte) (d >>> 4 & 15);  //4bitページ1,3
   907:        MainMemory.mmrM8[0x00100001 + a] = MainMemory.mmrM8[0x00000001 + a] = (byte) (d       & 15);  //4bitページ0,2
   908:        a >>>= 10;
   909:        int y = a - CRTC.crtR13GrYCurr[3] & 511;
   910:        CRTC.crtRasterStamp[y      ] = 0;
   911:        CRTC.crtRasterStamp[y + 512] = 0;
   912:        y = a - CRTC.crtR13GrYCurr[2] & 511;
   913:        CRTC.crtRasterStamp[y      ] = 0;
   914:        CRTC.crtRasterStamp[y + 512] = 0;
   915:        y = a - CRTC.crtR13GrYCurr[1] & 511;
   916:        CRTC.crtRasterStamp[y      ] = 0;
   917:        CRTC.crtRasterStamp[y + 512] = 0;
   918:        y = a - CRTC.crtR13GrYCurr[0] & 511;
   919:        CRTC.crtRasterStamp[y      ] = 0;
   920:        CRTC.crtRasterStamp[y + 512] = 0;
   921:      }
   922:     @Override protected void mmdWl (int a, int d) throws M68kException {
   923:        a &= 0x00c7fffe;
   924:        MainMemory.mmrM8[0x00180001 + a] = MainMemory.mmrM8[0x00080001 + a] = (byte) (d >>> 20 & 15);  //ページ1,3
   925:        MainMemory.mmrM8[0x00100001 + a] = MainMemory.mmrM8[0x00000001 + a] = (byte) (d >>> 16 & 15);  //ページ0,2
   926:        MainMemory.mmrM8[0x00180003 + a] = MainMemory.mmrM8[0x00080003 + a] = (byte) (d >>>  4 & 15);  //ページ1,3
   927:        MainMemory.mmrM8[0x00100003 + a] = MainMemory.mmrM8[0x00000003 + a] = (byte) (d        & 15);  //ページ0,2
   928:        a >>>= 10;
   929:        int y = a - CRTC.crtR13GrYCurr[3] & 511;
   930:        CRTC.crtRasterStamp[y      ] = 0;
   931:        CRTC.crtRasterStamp[y + 512] = 0;
   932:        y = a - CRTC.crtR13GrYCurr[2] & 511;
   933:        CRTC.crtRasterStamp[y      ] = 0;
   934:        CRTC.crtRasterStamp[y + 512] = 0;
   935:        y = a - CRTC.crtR13GrYCurr[1] & 511;
   936:        CRTC.crtRasterStamp[y      ] = 0;
   937:        CRTC.crtRasterStamp[y + 512] = 0;
   938:        y = a - CRTC.crtR13GrYCurr[0] & 511;
   939:        CRTC.crtRasterStamp[y      ] = 0;
   940:        CRTC.crtRasterStamp[y + 512] = 0;
   941:      }
   942:   },  //MMD_GM2
   943: 
   944:   //--------------------------------------------------------------------------------
   945:   //MMD_GG0 グラフィックス画面(512ドット65536色)
   946:   //
   947:   //  512ドット65536色
   948:   //                アドレス             アクセス                  格納
   949:   //    GG0  0x00c00000~0x00c7ffff  fedcba9876543210  ─┬  ............3210
   950:   //         0x00c80000~0x00cfffff                      ├  ............7654
   951:   //         0x00d00000~0x00d7ffff                      ├  ............ba98
   952:   //         0x00d80000~0x00dfffff                      └  ............fedc
   953:   //
   954:   MMD_GG0 {
   955:     @Override public String toString () {
   956:       return Multilingual.mlnJapanese ? "グラフィックス画面 (512 ドット 65536 色)" : "Graphics Screen (512 dots 65536 colors)";
   957:     }
   958:     //ピーク
   959:     @Override protected byte mmdPbs (int a) {
   960:       a &= XEiJ.BUS_MOTHER_MASK;
   961:       a += -(~a & 1) & 0x00100001;
   962:       return (byte) (MainMemory.mmrM8[a + 0x00080000] << 4 | MainMemory.mmrM8[a]);
   963:     }
   964:     @Override protected int mmdPbz (int a) {
   965:       a &= XEiJ.BUS_MOTHER_MASK;
   966:       a += -(~a & 1) & 0x00100001;
   967:       return MainMemory.mmrM8[a + 0x00080000] << 4 | MainMemory.mmrM8[a];
   968:     }
   969:     @Override protected int mmdPws (int a) {
   970:       a &= XEiJ.BUS_MOTHER_MASK;
   971:       return (short) (MainMemory.mmrM8[a + 0x00180001] << 12 | MainMemory.mmrM8[a + 0x00100001] << 8 | MainMemory.mmrM8[a + 0x00080001] << 4 | MainMemory.mmrM8[a + 1]);
   972:     }
   973:     @Override protected int mmdPwz (int a) {
   974:       a &= XEiJ.BUS_MOTHER_MASK;
   975:       return MainMemory.mmrM8[a + 0x00180001] << 12 | MainMemory.mmrM8[a + 0x00100001] << 8 | MainMemory.mmrM8[a + 0x00080001] << 4 | MainMemory.mmrM8[a + 1];
   976:     }
   977:     @Override protected int mmdPls (int a) {
   978:       a &= XEiJ.BUS_MOTHER_MASK;
   979:       return (MainMemory.mmrM8[a + 0x00180001] << 28 | MainMemory.mmrM8[a + 0x00100001] << 24 | MainMemory.mmrM8[a + 0x00080001] << 20 | MainMemory.mmrM8[a + 1] << 16 |
   980:               MainMemory.mmrM8[a + 0x00180003] << 12 | MainMemory.mmrM8[a + 0x00100003] << 8 | MainMemory.mmrM8[a + 0x00080003] << 4 | MainMemory.mmrM8[a + 3]);
   981:     }
   982:     //リード
   983:     @Override protected byte mmdRbs (int a) throws M68kException {
   984:        a &= XEiJ.BUS_MOTHER_MASK;
   985:        a += -(~a & 1) & 0x00100001;
   986:        return (byte) (MainMemory.mmrM8[a + 0x00080000] << 4 | MainMemory.mmrM8[a]);
   987:      }
   988:     @Override protected int mmdRbz (int a) throws M68kException {
   989:        a &= XEiJ.BUS_MOTHER_MASK;
   990:        a += -(~a & 1) & 0x00100001;
   991:        return MainMemory.mmrM8[a + 0x00080000] << 4 | MainMemory.mmrM8[a];
   992:      }
   993:     @Override protected int mmdRws (int a) throws M68kException {
   994:        a &= XEiJ.BUS_MOTHER_MASK;
   995:        return (short) (MainMemory.mmrM8[a + 0x00180001] << 12 | MainMemory.mmrM8[a + 0x00100001] << 8 | MainMemory.mmrM8[a + 0x00080001] << 4 | MainMemory.mmrM8[a + 1]);
   996:      }
   997:     @Override protected int mmdRwz (int a) throws M68kException {
   998:        a &= XEiJ.BUS_MOTHER_MASK;
   999:        return MainMemory.mmrM8[a + 0x00180001] << 12 | MainMemory.mmrM8[a + 0x00100001] << 8 | MainMemory.mmrM8[a + 0x00080001] << 4 | MainMemory.mmrM8[a + 1];
  1000:      }
  1001:     @Override protected int mmdRls (int a) throws M68kException {
  1002:        a &= XEiJ.BUS_MOTHER_MASK;
  1003:        return (MainMemory.mmrM8[a + 0x00180001] << 28 | MainMemory.mmrM8[a + 0x00100001] << 24 | MainMemory.mmrM8[a + 0x00080001] << 20 | MainMemory.mmrM8[a + 1] << 16 |
  1004:                MainMemory.mmrM8[a + 0x00180003] << 12 | MainMemory.mmrM8[a + 0x00100003] << 8 | MainMemory.mmrM8[a + 0x00080003] << 4 | MainMemory.mmrM8[a + 3]);
  1005:      }
  1006:     //ライト
  1007:     @Override protected void mmdWb (int a, int d) throws M68kException {
  1008:        a &= XEiJ.BUS_MOTHER_MASK;
  1009:        if (XEiJ.TEST_BIT_0_SHIFT ? a << 31 - 0 >= 0 : (a & 1) == 0) {
  1010:          MainMemory.mmrM8[a + 0x00180001] = (byte) (d << 24  >>> 28);
  1011:          MainMemory.mmrM8[a + 0x00100001] = (byte) (d          & 15);
  1012:          a >>= 10;
  1013:          int y = a - CRTC.crtR13GrYCurr[2] & 511;
  1014:          CRTC.crtRasterStamp[y      ] = 0;
  1015:          CRTC.crtRasterStamp[y + 512] = 0;
  1016:          y = a - CRTC.crtR13GrYCurr[3] & 511;
  1017:          CRTC.crtRasterStamp[y      ] = 0;
  1018:          CRTC.crtRasterStamp[y + 512] = 0;
  1019:        } else {
  1020:          MainMemory.mmrM8[a + 0x00080000] = (byte) (d << 24  >>> 28);
  1021:          MainMemory.mmrM8[a             ] = (byte) (d          & 15);
  1022:          a >>= 10;
  1023:          int y = a - CRTC.crtR13GrYCurr[0] & 511;
  1024:          CRTC.crtRasterStamp[y      ] = 0;
  1025:          CRTC.crtRasterStamp[y + 512] = 0;
  1026:          y = a - CRTC.crtR13GrYCurr[1] & 511;
  1027:          CRTC.crtRasterStamp[y      ] = 0;
  1028:          CRTC.crtRasterStamp[y + 512] = 0;
  1029:        }
  1030:      }
  1031:     @Override protected void mmdWw (int a, int d) throws M68kException {
  1032:        a &= XEiJ.BUS_MOTHER_MASK;
  1033:        MainMemory.mmrM8[a + 0x00180001] = (byte) ((char) d >>> 12);
  1034:        MainMemory.mmrM8[a + 0x00100001] = (byte) (d << 20  >>> 28);
  1035:        MainMemory.mmrM8[a + 0x00080001] = (byte) (d << 24  >>> 28);
  1036:        MainMemory.mmrM8[a + 0x00000001] = (byte) (d          & 15);
  1037:        a >>= 10;
  1038:        int y = a - CRTC.crtR13GrYCurr[0] & 511;
  1039:        CRTC.crtRasterStamp[y      ] = 0;
  1040:        CRTC.crtRasterStamp[y + 512] = 0;
  1041:        y = a - CRTC.crtR13GrYCurr[1] & 511;
  1042:        CRTC.crtRasterStamp[y      ] = 0;
  1043:        CRTC.crtRasterStamp[y + 512] = 0;
  1044:        y = a - CRTC.crtR13GrYCurr[2] & 511;
  1045:        CRTC.crtRasterStamp[y      ] = 0;
  1046:        CRTC.crtRasterStamp[y + 512] = 0;
  1047:        y = a - CRTC.crtR13GrYCurr[3] & 511;
  1048:        CRTC.crtRasterStamp[y      ] = 0;
  1049:        CRTC.crtRasterStamp[y + 512] = 0;
  1050:      }
  1051:     @Override protected void mmdWl (int a, int d) throws M68kException {
  1052:        a &= XEiJ.BUS_MOTHER_MASK;
  1053:        MainMemory.mmrM8[a + 0x00180001] = (byte) (d        >>> 28);
  1054:        MainMemory.mmrM8[a + 0x00100001] = (byte) (d <<  4  >>> 28);
  1055:        MainMemory.mmrM8[a + 0x00080001] = (byte) (d <<  8  >>> 28);
  1056:        MainMemory.mmrM8[a + 0x00000001] = (byte) (d << 12  >>> 28);
  1057:        MainMemory.mmrM8[a + 0x00180003] = (byte) ((char) d >>> 12);
  1058:        MainMemory.mmrM8[a + 0x00100003] = (byte) (d << 20  >>> 28);
  1059:        MainMemory.mmrM8[a + 0x00080003] = (byte) (d << 24  >>> 28);
  1060:        MainMemory.mmrM8[a + 0x00000003] = (byte) (d          & 15);
  1061:        a >>= 10;
  1062:        int y = a - CRTC.crtR13GrYCurr[0] & 511;
  1063:        CRTC.crtRasterStamp[y      ] = 0;
  1064:        CRTC.crtRasterStamp[y + 512] = 0;
  1065:        y = a - CRTC.crtR13GrYCurr[1] & 511;
  1066:        CRTC.crtRasterStamp[y      ] = 0;
  1067:        CRTC.crtRasterStamp[y + 512] = 0;
  1068:        y = a - CRTC.crtR13GrYCurr[2] & 511;
  1069:        CRTC.crtRasterStamp[y      ] = 0;
  1070:        CRTC.crtRasterStamp[y + 512] = 0;
  1071:        y = a - CRTC.crtR13GrYCurr[3] & 511;
  1072:        CRTC.crtRasterStamp[y      ] = 0;
  1073:        CRTC.crtRasterStamp[y + 512] = 0;
  1074:      }
  1075:   },  //MMD_GG0
  1076: 
  1077:   //--------------------------------------------------------------------------------
  1078:   //MMD_GH0 グラフィックス画面(1024ドット16色)
  1079:   //
  1080:   //  参照アドレス
  1081:   //    0b00000000_110Yyyyy_yyyyyXxx_xxxxxxx?
  1082:   //    +--------------------------+--------------------------+
  1083:   //    | 0x00c00000 .. 0x00c003ff | 0x00c00400 .. 0x00c007ff |
  1084:   //    | 0x00c00800    0x00c00bff | 0x00c00c00    0x00c00fff |
  1085:   //    |      :             :     |      :             :     |
  1086:   //    | 0x00cff000    0x00cff3ff | 0x00cff400    0x00cff7ff |
  1087:   //    | 0x00cff800 .. 0x00cffbff | 0x00cffc00 .. 0x00cfffff |
  1088:   //    +--------------------------+--------------------------+
  1089:   //    | 0x00d00000 .. 0x00d003ff | 0x00d00400 .. 0x00d007ff |
  1090:   //    | 0x00d00800    0x00d00bff | 0x00d00c00    0x00d00fff |
  1091:   //    |      :             :     |      :             :     |
  1092:   //    | 0x00dff000    0x00dff3ff | 0x00dff400    0x00dff7ff |
  1093:   //    | 0x00dff800 .. 0x00dffbff | 0x00dffc00 .. 0x00dfffff |
  1094:   //    +--------------------------+--------------------------+
  1095:   //
  1096:   //  格納アドレス
  1097:   //    0b00000000_110YXyyy_yyyyyyxx_xxxxxxx?
  1098:   //    +--------------------------+--------------------------+
  1099:   //    | 0x00c00000 .. 0x00c003ff | 0x00c80000 .. 0x00c803ff |
  1100:   //    | 0x00c00400    0x00c007ff | 0x00c80400    0x00c807ff |
  1101:   //    |      :     G0      :     |      :     G1      :     |
  1102:   //    | 0x00c7f800    0x00c7fbff | 0x00cff800    0x00cffbff |
  1103:   //    | 0x00c7fc00 .. 0x00c7ffff | 0x00cffc00 .. 0x00cfffff |
  1104:   //    +--------------------------+--------------------------+
  1105:   //    | 0x00d00000 .. 0x00d003ff | 0x00d80000 .. 0x00d803ff |
  1106:   //    | 0x00d00400    0x00d007ff | 0x00d80400    0x00d807ff |
  1107:   //    |      :     G2      :     |      :     G3      :     |
  1108:   //    | 0x00d7f800    0x00d7fbff | 0x00dff800    0x00dffbff |
  1109:   //    | 0x00d7fc00 .. 0x00d7ffff | 0x00dffc00 .. 0x00dfffff |
  1110:   //    +--------------------------+--------------------------+
  1111:   //
  1112:   //    perl -e "@m=(0,1,2,3);sub f{my($a)=@_;my$x=$a>>1&1023;my$y=$a>>11&1023;($a&0x00c00001)+($m[($y>>8&2)+($x>>9&1)]<<19)+(($y&511)<<10)+(($x&511)<<1);}my@a=(0xc00000,0xc003ff,0xc00400,0xc007ff,0xc00800,0xc00bff,0xc00c00,0xc00fff,0xcff000,0xcff3ff,0xcff400,0xcff7ff,0xcff800,0xcffbff,0xcffc00,0xcfffff,0xd00000,0xd003ff,0xd00400,0xd007ff,0xd00800,0xd00bff,0xd00c00,0xd00fff,0xdff000,0xdff3ff,0xdff400,0xdff7ff,0xdff800,0xdffbff,0xdffc00,0xdfffff);for$v(0..7){print'  //    ';for$u(0..3){$a=$a[4*$v+$u];$b=f($a);printf'  0x%08x',$b;}print qq@\n@;}"
  1113:   //    perl -e "sub f{my($a)=@_;($a&0x00c00000+(1<<20)+1023)+($a<<9&1<<19)+($a>>1&511<<10);}my@a=(0xc00000,0xc003ff,0xc00400,0xc007ff,0xc00800,0xc00bff,0xc00c00,0xc00fff,0xcff000,0xcff3ff,0xcff400,0xcff7ff,0xcff800,0xcffbff,0xcffc00,0xcfffff,0xd00000,0xd003ff,0xd00400,0xd007ff,0xd00800,0xd00bff,0xd00c00,0xd00fff,0xdff000,0xdff3ff,0xdff400,0xdff7ff,0xdff800,0xdffbff,0xdffc00,0xdfffff);for$v(0..7){print'  //    ';for$u(0..3){$a=$a[4*$v+$u];$b=f($a);printf'  0x%08x',$b;}print qq@\n@;}"
  1114:   //      0x00c00000  0x00c003ff  0x00c80000  0x00c803ff
  1115:   //      0x00c00400  0x00c007ff  0x00c80400  0x00c807ff
  1116:   //      0x00c7f800  0x00c7fbff  0x00cff800  0x00cffbff
  1117:   //      0x00c7fc00  0x00c7ffff  0x00cffc00  0x00cfffff
  1118:   //      0x00d00000  0x00d003ff  0x00d80000  0x00d803ff
  1119:   //      0x00d00400  0x00d007ff  0x00d80400  0x00d807ff
  1120:   //      0x00d7f800  0x00d7fbff  0x00dff800  0x00dffbff
  1121:   //      0x00d7fc00  0x00d7ffff  0x00dffc00  0x00dfffff
  1122:   //
  1123:   MMD_GH0 {
  1124:     @Override public String toString () {
  1125:       return Multilingual.mlnJapanese ? "グラフィックス画面 (1024 ドット 16 色)" : "Graphics Screen (1024 dots 16 colors)";
  1126:     }
  1127:     //ピーク
  1128:     @Override protected byte mmdPbs (int a) {
  1129:       int b0 = (a & 0x00c00000 + (1 << 20) + 1023) + (a << 9 & 1 << 19) + (a >>> 1 & 511 << 10);
  1130:       return MainMemory.mmrM8[b0];
  1131:     }
  1132:     @Override protected int mmdPbz (int a) {
  1133:       int b0 = (a & 0x00c00000 + (1 << 20) + 1023) + (a << 9 & 1 << 19) + (a >>> 1 & 511 << 10);
  1134:       return MainMemory.mmrM8[b0];
  1135:     }
  1136:     @Override protected int mmdPws (int a) {
  1137:       int b0 = (a & 0x00c00000 + (1 << 20) + 1023) + (a << 9 & 1 << 19) + (a >>> 1 & 511 << 10);
  1138:       return MainMemory.mmrM8[b0 + 1];
  1139:     }
  1140:     @Override protected int mmdPwz (int a) {
  1141:       int b0 = (a & 0x00c00000 + (1 << 20) + 1023) + (a << 9 & 1 << 19) + (a >>> 1 & 511 << 10);
  1142:       return MainMemory.mmrM8[b0 + 1];
  1143:     }
  1144:     @Override protected int mmdPls (int a) {
  1145:       //4bitページを跨ぐ場合があることに注意
  1146:       int b0 = (a & 0x00c00000 + (1 << 20) + 1023) + (a << 9 & 1 << 19) + (a >>> 1 & 511 << 10);
  1147:       a += 2;
  1148:       int b2 = (a & 0x00c00000 + (1 << 20) + 1023) + (a << 9 & 1 << 19) + (a >>> 1 & 511 << 10);
  1149:       return MainMemory.mmrM8[b0 + 1] << 16 | MainMemory.mmrM8[b2 + 1];
  1150:     }
  1151:     //リード
  1152:     @Override protected byte mmdRbs (int a) throws M68kException {
  1153:        int b0 = (a & 0x00c00000 + (1 << 20) + 1023) + (a << 9 & 1 << 19) + (a >>> 1 & 511 << 10);
  1154:        return MainMemory.mmrM8[b0];
  1155:      }
  1156:     @Override protected int mmdRbz (int a) throws M68kException {
  1157:        int b0 = (a & 0x00c00000 + (1 << 20) + 1023) + (a << 9 & 1 << 19) + (a >>> 1 & 511 << 10);
  1158:        return MainMemory.mmrM8[b0];
  1159:      }
  1160:     @Override protected int mmdRws (int a) throws M68kException {
  1161:        int b0 = (a & 0x00c00000 + (1 << 20) + 1023) + (a << 9 & 1 << 19) + (a >>> 1 & 511 << 10);
  1162:        return MainMemory.mmrM8[b0 + 1];
  1163:      }
  1164:     @Override protected int mmdRwz (int a) throws M68kException {
  1165:        int b0 = (a & 0x00c00000 + (1 << 20) + 1023) + (a << 9 & 1 << 19) + (a >>> 1 & 511 << 10);
  1166:        return MainMemory.mmrM8[b0 + 1];
  1167:      }
  1168:     @Override protected int mmdRls (int a) throws M68kException {
  1169:        //4bitページを跨ぐ場合があることに注意
  1170:        int b0 = (a & 0x00c00000 + (1 << 20) + 1023) + (a << 9 & 1 << 19) + (a >>> 1 & 511 << 10);
  1171:        a += 2;
  1172:        int b2 = (a & 0x00c00000 + (1 << 20) + 1023) + (a << 9 & 1 << 19) + (a >>> 1 & 511 << 10);
  1173:        return MainMemory.mmrM8[b0 + 1] << 16 | MainMemory.mmrM8[b2 + 1];
  1174:      }
  1175:     //ライト
  1176:     @Override protected void mmdWb (int a, int d) throws M68kException {
  1177:        if ((a & 1) != 0) {
  1178:          CRTC.crtRasterStamp[(a >> 11) - CRTC.crtR13GrYCurr[0] & 1023] = 0;
  1179:          int b0 = (a & 0x00c00000 + (1 << 20) + 1023) + (a << 9 & 1 << 19) + (a >>> 1 & 511 << 10);
  1180:          MainMemory.mmrM8[b0] = (byte) (d & 15);
  1181:        }
  1182:      }
  1183:     @Override protected void mmdWw (int a, int d) throws M68kException {
  1184:        CRTC.crtRasterStamp[(a >> 11) - CRTC.crtR13GrYCurr[0] & 1023] = 0;
  1185:        int b0 = (a & 0x00c00000 + (1 << 20) + 1023) + (a << 9 & 1 << 19) + (a >>> 1 & 511 << 10);
  1186:        MainMemory.mmrM8[b0 + 1] = (byte) (d & 15);
  1187:      }
  1188:     @Override protected void mmdWl (int a, int d) throws M68kException {
  1189:        CRTC.crtRasterStamp[(a >> 11) - CRTC.crtR13GrYCurr[0] & 1023] = 0;
  1190:        //4bitページを跨ぐ場合があることに注意
  1191:        int b0 = (a & 0x00c00000 + (1 << 20) + 1023) + (a << 9 & 1 << 19) + (a >>> 1 & 511 << 10);
  1192:        a += 2;
  1193:        int b2 = (a & 0x00c00000 + (1 << 20) + 1023) + (a << 9 & 1 << 19) + (a >>> 1 & 511 << 10);
  1194:        MainMemory.mmrM8[b0 + 1] = (byte) (d >>> 16 & 15);
  1195:        MainMemory.mmrM8[b2 + 1] = (byte) (d & 15);
  1196:      }
  1197:   },  //MMD_GH0
  1198: 
  1199:   //--------------------------------------------------------------------------------
  1200:   //MMD_GI0 グラフィックス画面(1024ドット256色)
  1201:   //
  1202:   //  参照アドレスと格納アドレスはGH0と同じ
  1203:   //
  1204:   MMD_GI0 {
  1205:     @Override public String toString () {
  1206:       return Multilingual.mlnJapanese ? "グラフィックス画面 (1024 ドット 256 色)" : "Graphics Screen (1024 dots 256 colors)";
  1207:     }
  1208:     //ピーク
  1209:     @Override protected byte mmdPbs (int a) {
  1210:       int b0 = XEiJ.BUS_MODIFIED_256_PAGE + (a & (1 << 20) + 1023) + (a << 9 & 1 << 19) + (a >>> 1 & 511 << 10);
  1211:       return MainMemory.mmrM8[b0];
  1212:     }
  1213:     @Override protected int mmdPbz (int a) {
  1214:       int b0 = XEiJ.BUS_MODIFIED_256_PAGE + (a & (1 << 20) + 1023) + (a << 9 & 1 << 19) + (a >>> 1 & 511 << 10);
  1215:       return MainMemory.mmrM8[b0] & 255;
  1216:     }
  1217:     @Override protected int mmdPws (int a) {
  1218:       int b0 = XEiJ.BUS_MODIFIED_256_PAGE + (a & (1 << 20) + 1023) + (a << 9 & 1 << 19) + (a >>> 1 & 511 << 10);
  1219:       return MainMemory.mmrM8[b0 + 1] & 255;
  1220:     }
  1221:     @Override protected int mmdPwz (int a) {
  1222:       int b0 = XEiJ.BUS_MODIFIED_256_PAGE + (a & (1 << 20) + 1023) + (a << 9 & 1 << 19) + (a >>> 1 & 511 << 10);
  1223:       return MainMemory.mmrM8[b0 + 1] & 255;
  1224:     }
  1225:     @Override protected int mmdPls (int a) {
  1226:       //4bitページを跨ぐ場合があることに注意
  1227:       int b0 = XEiJ.BUS_MODIFIED_256_PAGE + (a & (1 << 20) + 1023) + (a << 9 & 1 << 19) + (a >>> 1 & 511 << 10);
  1228:       a += 2;
  1229:       int b2 = XEiJ.BUS_MODIFIED_256_PAGE + (a & (1 << 20) + 1023) + (a << 9 & 1 << 19) + (a >>> 1 & 511 << 10);
  1230:       return (MainMemory.mmrM8[b0 + 1] & 255) << 16 | MainMemory.mmrM8[b2 + 1] & 255;
  1231:     }
  1232:     //リード
  1233:     @Override protected byte mmdRbs (int a) throws M68kException {
  1234:        int b0 = XEiJ.BUS_MODIFIED_256_PAGE + (a & (1 << 20) + 1023) + (a << 9 & 1 << 19) + (a >>> 1 & 511 << 10);
  1235:        return MainMemory.mmrM8[b0];
  1236:      }
  1237:     @Override protected int mmdRbz (int a) throws M68kException {
  1238:        int b0 = XEiJ.BUS_MODIFIED_256_PAGE + (a & (1 << 20) + 1023) + (a << 9 & 1 << 19) + (a >>> 1 & 511 << 10);
  1239:        return MainMemory.mmrM8[b0] & 255;
  1240:      }
  1241:     @Override protected int mmdRws (int a) throws M68kException {
  1242:        int b0 = XEiJ.BUS_MODIFIED_256_PAGE + (a & (1 << 20) + 1023) + (a << 9 & 1 << 19) + (a >>> 1 & 511 << 10);
  1243:        return MainMemory.mmrM8[b0 + 1] & 255;
  1244:      }
  1245:     @Override protected int mmdRwz (int a) throws M68kException {
  1246:        int b0 = XEiJ.BUS_MODIFIED_256_PAGE + (a & (1 << 20) + 1023) + (a << 9 & 1 << 19) + (a >>> 1 & 511 << 10);
  1247:        return MainMemory.mmrM8[b0 + 1] & 255;
  1248:      }
  1249:     @Override protected int mmdRls (int a) throws M68kException {
  1250:        //4bitページを跨ぐ場合があることに注意
  1251:        int b0 = XEiJ.BUS_MODIFIED_256_PAGE + (a & (1 << 20) + 1023) + (a << 9 & 1 << 19) + (a >>> 1 & 511 << 10);
  1252:        a += 2;
  1253:        int b2 = XEiJ.BUS_MODIFIED_256_PAGE + (a & (1 << 20) + 1023) + (a << 9 & 1 << 19) + (a >>> 1 & 511 << 10);
  1254:        return (MainMemory.mmrM8[b0 + 1] & 255) << 16 | MainMemory.mmrM8[b2 + 1] & 255;
  1255:      }
  1256:     //ライト
  1257:     @Override protected void mmdWb (int a, int d) throws M68kException {
  1258:        if ((a & 1) != 0) {
  1259:          CRTC.crtRasterStamp[(a >> 11) - CRTC.crtR13GrYCurr[0] & 1023] = 0;
  1260:          int b0 = XEiJ.BUS_MODIFIED_256_PAGE + (a & (1 << 20) + 1023) + (a << 9 & 1 << 19) + (a >>> 1 & 511 << 10);
  1261:          MainMemory.mmrM8[b0] = (byte) d;
  1262:        }
  1263:      }
  1264:     @Override protected void mmdWw (int a, int d) throws M68kException {
  1265:        CRTC.crtRasterStamp[(a >> 11) - CRTC.crtR13GrYCurr[0] & 1023] = 0;
  1266:        int b0 = XEiJ.BUS_MODIFIED_256_PAGE + (a & (1 << 20) + 1023) + (a << 9 & 1 << 19) + (a >>> 1 & 511 << 10);
  1267:        MainMemory.mmrM8[b0 + 1] = (byte) d;
  1268:      }
  1269:     @Override protected void mmdWl (int a, int d) throws M68kException {
  1270:        CRTC.crtRasterStamp[(a >> 11) - CRTC.crtR13GrYCurr[0] & 1023] = 0;
  1271:        //4bitページを跨ぐ場合があることに注意
  1272:        int b0 = XEiJ.BUS_MODIFIED_256_PAGE + (a & (1 << 20) + 1023) + (a << 9 & 1 << 19) + (a >>> 1 & 511 << 10);
  1273:        a += 2;
  1274:        int b2 = XEiJ.BUS_MODIFIED_256_PAGE + (a & (1 << 20) + 1023) + (a << 9 & 1 << 19) + (a >>> 1 & 511 << 10);
  1275:        MainMemory.mmrM8[b0 + 1] = (byte) (d >>> 16);
  1276:        MainMemory.mmrM8[b2 + 1] = (byte) d;
  1277:      }
  1278:   },  //MMD_GI0
  1279: 
  1280:   //--------------------------------------------------------------------------------
  1281:   //MMD_GJ0 グラフィックス画面(1024ドット65536色)
  1282:   //
  1283:   //  参照アドレスと格納アドレスはGH0と同じ
  1284:   //
  1285:   MMD_GJ0 {
  1286:     @Override public String toString () {
  1287:       return Multilingual.mlnJapanese ? "グラフィックス画面 (1024 ドット 65536 色)" : "Graphics Screen (1024 dots 65536 colors)";
  1288:     }
  1289:     //ピーク
  1290:     @Override protected byte mmdPbs (int a) {
  1291:       int b0 = XEiJ.BUS_MODIFIED_65536_PAGE + (a & (1 << 20) + 1023) + (a << 9 & 1 << 19) + (a >>> 1 & 511 << 10);
  1292:       return MainMemory.mmrM8[b0];
  1293:     }
  1294:     @Override protected int mmdPbz (int a) {
  1295:       int b0 = XEiJ.BUS_MODIFIED_65536_PAGE + (a & (1 << 20) + 1023) + (a << 9 & 1 << 19) + (a >>> 1 & 511 << 10);
  1296:       return MainMemory.mmrM8[b0] & 255;
  1297:     }
  1298:     @Override protected int mmdPws (int a) {
  1299:       int b0 = XEiJ.BUS_MODIFIED_65536_PAGE + (a & (1 << 20) + 1023) + (a << 9 & 1 << 19) + (a >>> 1 & 511 << 10);
  1300:       return MainMemory.mmrM8[b0] << 8 | MainMemory.mmrM8[b0 + 1] & 255;
  1301:     }
  1302:     @Override protected int mmdPwz (int a) {
  1303:       int b0 = XEiJ.BUS_MODIFIED_65536_PAGE + (a & (1 << 20) + 1023) + (a << 9 & 1 << 19) + (a >>> 1 & 511 << 10);
  1304:       return (char) (MainMemory.mmrM8[b0] << 8 | MainMemory.mmrM8[b0 + 1] & 255);
  1305:     }
  1306:     @Override protected int mmdPls (int a) {
  1307:        //4bitページを跨ぐ場合があることに注意
  1308:       int b0 = XEiJ.BUS_MODIFIED_65536_PAGE + (a & (1 << 20) + 1023) + (a << 9 & 1 << 19) + (a >>> 1 & 511 << 10);
  1309:       a += 2;
  1310:       int b2 = XEiJ.BUS_MODIFIED_65536_PAGE + (a & (1 << 20) + 1023) + (a << 9 & 1 << 19) + (a >>> 1 & 511 << 10);
  1311:       return (MainMemory.mmrM8[b0] << 24 | (MainMemory.mmrM8[b0 + 1] & 255) << 16 |
  1312:               (char) (MainMemory.mmrM8[b2] << 8 | MainMemory.mmrM8[b2 + 1] & 255));
  1313:     }
  1314:     //リード
  1315:     @Override protected byte mmdRbs (int a) throws M68kException {
  1316:        return MainMemory.mmrM8[XEiJ.BUS_MODIFIED_65536_PAGE + (a & (1 << 20) + 1023) + (a << 9 & 1 << 19) + (a >>> 1 & 511 << 10)];
  1317:      }
  1318:     @Override protected int mmdRbz (int a) throws M68kException {
  1319:        return MainMemory.mmrM8[XEiJ.BUS_MODIFIED_65536_PAGE + (a & (1 << 20) + 1023) + (a << 9 & 1 << 19) + (a >>> 1 & 511 << 10)] & 255;
  1320:      }
  1321:     @Override protected int mmdRws (int a) throws M68kException {
  1322:        int b0 = XEiJ.BUS_MODIFIED_65536_PAGE + (a & (1 << 20) + 1023) + (a << 9 & 1 << 19) + (a >>> 1 & 511 << 10);
  1323:        return MainMemory.mmrM8[b0] << 8 | MainMemory.mmrM8[b0 + 1] & 255;
  1324:      }
  1325:     @Override protected int mmdRwz (int a) throws M68kException {
  1326:        int b0 = XEiJ.BUS_MODIFIED_65536_PAGE + (a & (1 << 20) + 1023) + (a << 9 & 1 << 19) + (a >>> 1 & 511 << 10);
  1327:        return (char) (MainMemory.mmrM8[b0] << 8 | MainMemory.mmrM8[b0 + 1] & 255);
  1328:      }
  1329:     @Override protected int mmdRls (int a) throws M68kException {
  1330:        //4bitページを跨ぐ場合があることに注意
  1331:        int b0 = XEiJ.BUS_MODIFIED_65536_PAGE + (a & (1 << 20) + 1023) + (a << 9 & 1 << 19) + (a >>> 1 & 511 << 10);
  1332:        a += 2;
  1333:        int b2 = XEiJ.BUS_MODIFIED_65536_PAGE + (a & (1 << 20) + 1023) + (a << 9 & 1 << 19) + (a >>> 1 & 511 << 10);
  1334:        return (MainMemory.mmrM8[b0] << 24 | (MainMemory.mmrM8[b0 + 1] & 255) << 16 |
  1335:                (char) (MainMemory.mmrM8[b2] << 8 | MainMemory.mmrM8[b2 + 1] & 255));
  1336:      }
  1337:     //ライト
  1338:     @Override protected void mmdWb (int a, int d) throws M68kException {
  1339:        if ((a & 1) != 0) {
  1340:          CRTC.crtRasterStamp[(a >> 11) - CRTC.crtR13GrYCurr[0] & 1023] = 0;
  1341:          MainMemory.mmrM8[XEiJ.BUS_MODIFIED_65536_PAGE + (a & (1 << 20) + 1023) + (a << 9 & 1 << 19) + (a >>> 1 & 511 << 10)] = (byte) d;
  1342:        }
  1343:      }
  1344:     @Override protected void mmdWw (int a, int d) throws M68kException {
  1345:        CRTC.crtRasterStamp[(a >> 11) - CRTC.crtR13GrYCurr[0] & 1023] = 0;
  1346:        int b0 = XEiJ.BUS_MODIFIED_65536_PAGE + (a & (1 << 20) + 1023) + (a << 9 & 1 << 19) + (a >>> 1 & 511 << 10);
  1347:        MainMemory.mmrM8[b0] = (byte) (d >> 8);
  1348:        MainMemory.mmrM8[b0 + 1] = (byte) d;
  1349:      }
  1350:     @Override protected void mmdWl (int a, int d) throws M68kException {
  1351:        CRTC.crtRasterStamp[(a >> 11) - CRTC.crtR13GrYCurr[0] & 1023] = 0;
  1352:        //4bitページを跨ぐ場合があることに注意
  1353:        int b0 = XEiJ.BUS_MODIFIED_65536_PAGE + (a & (1 << 20) + 1023) + (a << 9 & 1 << 19) + (a >>> 1 & 511 << 10);
  1354:        a += 2;
  1355:        int b2 = XEiJ.BUS_MODIFIED_65536_PAGE + (a & (1 << 20) + 1023) + (a << 9 & 1 << 19) + (a >>> 1 & 511 << 10);
  1356:        MainMemory.mmrM8[b0] = (byte) (d >>> 24);
  1357:        MainMemory.mmrM8[b0 + 1] = (byte) (d >>> 16);
  1358:        MainMemory.mmrM8[b2] = (byte) (d >>> 8);
  1359:        MainMemory.mmrM8[b2 + 1] = (byte) d;
  1360:      }
  1361:   },  //MMD_GJ0
  1362: 
  1363:   //--------------------------------------------------------------------------------
  1364:   //MMD_TXT テキスト画面
  1365:   MMD_TXT {
  1366:     @Override public String toString () {
  1367:       return Multilingual.mlnJapanese ? "テキスト画面" : "Text Screen";
  1368:     }
  1369:     //ピーク
  1370:     @Override protected byte mmdPbs (int a) {
  1371:       a &= XEiJ.BUS_MOTHER_MASK;
  1372:       return MainMemory.mmrM8[a];
  1373:     }
  1374:     @Override protected int mmdPbz (int a) {
  1375:       a &= XEiJ.BUS_MOTHER_MASK;
  1376:       return MainMemory.mmrM8[a] & 255;
  1377:     }
  1378:     @Override protected int mmdPws (int a) {
  1379:       a &= XEiJ.BUS_MOTHER_MASK;
  1380:       if (MainMemory.MMR_USE_BYTE_BUFFER) {
  1381:         return MainMemory.mmrBuffer.getShort (a);
  1382:       } else {
  1383:         return MainMemory.mmrM8[a] << 8 | MainMemory.mmrM8[a + 1] & 255;
  1384:       }
  1385:     }
  1386:     @Override protected int mmdPwz (int a) {
  1387:       a &= XEiJ.BUS_MOTHER_MASK;
  1388:       if (MainMemory.MMR_USE_BYTE_BUFFER) {
  1389:         return MainMemory.mmrBuffer.getChar (a);
  1390:       } else {
  1391:         return (char) (MainMemory.mmrM8[a] << 8 | MainMemory.mmrM8[a + 1] & 255);
  1392:       }
  1393:     }
  1394:     @Override protected int mmdPls (int a) {
  1395:       a &= XEiJ.BUS_MOTHER_MASK;
  1396:       if (MainMemory.MMR_USE_BYTE_BUFFER) {
  1397:         return MainMemory.mmrBuffer.getInt (a);
  1398:       } else {
  1399:         return MainMemory.mmrM8[a] << 24 | (MainMemory.mmrM8[a + 1] & 255) << 16 | (char) (MainMemory.mmrM8[a + 2] << 8 | MainMemory.mmrM8[a + 3] & 255);
  1400:       }
  1401:     }
  1402:     //リード
  1403:     @Override protected byte mmdRbs (int a) throws M68kException {
  1404:        a &= XEiJ.BUS_MOTHER_MASK;
  1405:        return MainMemory.mmrM8[a];
  1406:      }
  1407:     @Override protected int mmdRbz (int a) throws M68kException {
  1408:        a &= XEiJ.BUS_MOTHER_MASK;
  1409:        return MainMemory.mmrM8[a] & 255;
  1410:      }
  1411:     @Override protected int mmdRws (int a) throws M68kException {
  1412:        a &= XEiJ.BUS_MOTHER_MASK;
  1413:        if (MainMemory.MMR_USE_BYTE_BUFFER) {
  1414:          return MainMemory.mmrBuffer.getShort (a);
  1415:        } else {
  1416:          return MainMemory.mmrM8[a] << 8 | MainMemory.mmrM8[a + 1] & 255;
  1417:        }
  1418:      }
  1419:     @Override protected int mmdRwz (int a) throws M68kException {
  1420:        a &= XEiJ.BUS_MOTHER_MASK;
  1421:        if (MainMemory.MMR_USE_BYTE_BUFFER) {
  1422:          return MainMemory.mmrBuffer.getChar (a);
  1423:        } else {
  1424:          return (char) (MainMemory.mmrM8[a] << 8 | MainMemory.mmrM8[a + 1] & 255);
  1425:        }
  1426:      }
  1427:     @Override protected int mmdRls (int a) throws M68kException {
  1428:        a &= XEiJ.BUS_MOTHER_MASK;
  1429:        if (MainMemory.MMR_USE_BYTE_BUFFER) {
  1430:          return MainMemory.mmrBuffer.getInt (a);
  1431:        } else {
  1432:          return MainMemory.mmrM8[a] << 24 | (MainMemory.mmrM8[a + 1] & 255) << 16 | (char) (MainMemory.mmrM8[a + 2] << 8 | MainMemory.mmrM8[a + 3] & 255);
  1433:        }
  1434:      }
  1435:     //ライト
  1436:     @Override protected void mmdWb (int a, int d) throws M68kException {
  1437:        a &= XEiJ.BUS_MOTHER_MASK;
  1438:        int x;  //マスク
  1439:        if (CRTC.crtSimAccess) {  //同時アクセスあり
  1440:          a &= 0x00e1ffff;
  1441:          if (CRTC.crtBitMask) {  //同時アクセスあり,ビットマスクあり
  1442:            d &= ~(x = CRTC.crtR23Mask >> ((~a & 1) << 3));
  1443:            if (CRTC.crtSimPlane0) {
  1444:              MainMemory.mmrM8[a             ] = (byte) (MainMemory.mmrM8[a             ] & x | d);
  1445:            }
  1446:            if (CRTC.crtSimPlane1) {
  1447:              MainMemory.mmrM8[a + 0x00020000] = (byte) (MainMemory.mmrM8[a + 0x00020000] & x | d);
  1448:            }
  1449:            if (CRTC.crtSimPlane2) {
  1450:              MainMemory.mmrM8[a + 0x00040000] = (byte) (MainMemory.mmrM8[a + 0x00040000] & x | d);
  1451:            }
  1452:            if (CRTC.crtSimPlane3) {
  1453:              MainMemory.mmrM8[a + 0x00060000] = (byte) (MainMemory.mmrM8[a + 0x00060000] & x | d);
  1454:            }
  1455:          } else {  //同時アクセスあり,ビットマスクなし
  1456:            if (CRTC.crtSimPlane0) {
  1457:              MainMemory.mmrM8[a             ] = (byte) d;
  1458:            }
  1459:            if (CRTC.crtSimPlane1) {
  1460:              MainMemory.mmrM8[a + 0x00020000] = (byte) d;
  1461:            }
  1462:            if (CRTC.crtSimPlane2) {
  1463:              MainMemory.mmrM8[a + 0x00040000] = (byte) d;
  1464:            }
  1465:            if (CRTC.crtSimPlane3) {
  1466:              MainMemory.mmrM8[a + 0x00060000] = (byte) d;
  1467:            }
  1468:          }
  1469:        } else if (CRTC.crtBitMask) {  //同時アクセスなし,ビットマスクあり
  1470:          x = CRTC.crtR23Mask >> ((~a & 1) << 3);
  1471:          MainMemory.mmrM8[a] = (byte) (MainMemory.mmrM8[a] & x | d & ~x);
  1472:        } else {  //同時アクセスなし,ビットマスクなし
  1473:          MainMemory.mmrM8[a] = (byte) d;
  1474:        }
  1475:        CRTC.crtRasterStamp[((a & 0x0001ffff) >> 7) - CRTC.crtR11TxYCurr & 1023] = 0;  //同時アクセスやビットマスクで1ピクセルも書き換えなくても更新することになる
  1476:      }  //mmdWb
  1477:     @Override protected void mmdWw (int a, int d) throws M68kException {
  1478:        a &= XEiJ.BUS_MOTHER_MASK;
  1479:        int e;  //上位バイトのデータ
  1480:        int x;  //下位バイトのマスク
  1481:        int y;  //上位バイトのマスク
  1482:        if (CRTC.crtSimAccess) {  //同時アクセスあり
  1483:          a &= 0x00e1ffff;
  1484:          if (CRTC.crtBitMask) {  //同時アクセスあり,ビットマスクあり
  1485:            e = d >> 8 & ~(y = (x = CRTC.crtR23Mask) >> 8);
  1486:            d &= ~x;
  1487:            if (CRTC.crtSimPlane0) {
  1488:              MainMemory.mmrM8[a             ] = (byte) (MainMemory.mmrM8[a             ] & y | e);
  1489:              MainMemory.mmrM8[a + 0x00000001] = (byte) (MainMemory.mmrM8[a + 0x00000001] & x | d);
  1490:            }
  1491:            if (CRTC.crtSimPlane1) {
  1492:              MainMemory.mmrM8[a + 0x00020000] = (byte) (MainMemory.mmrM8[a + 0x00020000] & y | e);
  1493:              MainMemory.mmrM8[a + 0x00020001] = (byte) (MainMemory.mmrM8[a + 0x00020001] & x | d);
  1494:            }
  1495:            if (CRTC.crtSimPlane2) {
  1496:              MainMemory.mmrM8[a + 0x00040000] = (byte) (MainMemory.mmrM8[a + 0x00040000] & y | e);
  1497:              MainMemory.mmrM8[a + 0x00040001] = (byte) (MainMemory.mmrM8[a + 0x00040001] & x | d);
  1498:            }
  1499:            if (CRTC.crtSimPlane3) {
  1500:              MainMemory.mmrM8[a + 0x00060000] = (byte) (MainMemory.mmrM8[a + 0x00060000] & y | e);
  1501:              MainMemory.mmrM8[a + 0x00060001] = (byte) (MainMemory.mmrM8[a + 0x00060001] & x | d);
  1502:            }
  1503:          } else {  //同時アクセスあり,ビットマスクなし
  1504:            e = d >> 8;
  1505:            if (CRTC.crtSimPlane0) {
  1506:              MainMemory.mmrM8[a             ] = (byte) e;
  1507:              MainMemory.mmrM8[a + 0x00000001] = (byte) d;
  1508:            }
  1509:            if (CRTC.crtSimPlane1) {
  1510:              MainMemory.mmrM8[a + 0x00020000] = (byte) e;
  1511:              MainMemory.mmrM8[a + 0x00020001] = (byte) d;
  1512:            }
  1513:            if (CRTC.crtSimPlane2) {
  1514:              MainMemory.mmrM8[a + 0x00040000] = (byte) e;
  1515:              MainMemory.mmrM8[a + 0x00040001] = (byte) d;
  1516:            }
  1517:            if (CRTC.crtSimPlane3) {
  1518:              MainMemory.mmrM8[a + 0x00060000] = (byte) e;
  1519:              MainMemory.mmrM8[a + 0x00060001] = (byte) d;
  1520:            }
  1521:          }
  1522:        } else if (CRTC.crtBitMask) {  //同時アクセスなし,ビットマスクあり
  1523:          y = (x = CRTC.crtR23Mask) >> 8;
  1524:          MainMemory.mmrM8[a    ] = (byte) (MainMemory.mmrM8[a    ] & y | (d >> 8) & ~y);
  1525:          MainMemory.mmrM8[a + 1] = (byte) (MainMemory.mmrM8[a + 1] & x |  d       & ~x);
  1526:        } else {  //同時アクセスなし,ビットマスクなし
  1527:          if (MainMemory.MMR_USE_BYTE_BUFFER) {
  1528:            MainMemory.mmrBuffer.putShort (a, (short) d);
  1529:          } else {
  1530:            MainMemory.mmrM8[a    ] = (byte) (d >> 8);
  1531:            MainMemory.mmrM8[a + 1] = (byte)  d;
  1532:          }
  1533:        }
  1534:        CRTC.crtRasterStamp[((a & 0x0001ffff) >> 7) - CRTC.crtR11TxYCurr & 1023] = 0;  //同時アクセスやビットマスクで1ピクセルも書き換えなくても更新することになる
  1535:      }  //mmdWw
  1536:     @Override protected void mmdWl (int a, int d) throws M68kException {
  1537:        a &= XEiJ.BUS_MOTHER_MASK;
  1538:        int e;  //下位ワードの上位バイトのデータ
  1539:        int f;  //上位ワードの下位バイトのデータ
  1540:        int g;  //上位ワードの上位バイトのデータ
  1541:        int x;  //下位バイトのマスク
  1542:        int y;  //上位バイトのマスク
  1543:        if (CRTC.crtSimAccess) {  //同時アクセスあり
  1544:          a &= 0x00e1ffff;
  1545:          if (CRTC.crtBitMask) {  //同時アクセスあり,ビットマスクあり
  1546:            g = d >> 24 & ~(y = (x = CRTC.crtR23Mask) >> 8);
  1547:            f = d >> 16 & ~x;
  1548:            e = d >>  8 & ~y;
  1549:            d &= ~x;
  1550:            if (CRTC.crtSimPlane0) {
  1551:              MainMemory.mmrM8[a             ] = (byte) (MainMemory.mmrM8[a             ] & y | g);
  1552:              MainMemory.mmrM8[a + 0x00000001] = (byte) (MainMemory.mmrM8[a + 0x00000001] & x | f);
  1553:              MainMemory.mmrM8[a + 0x00000002] = (byte) (MainMemory.mmrM8[a + 0x00000002] & y | e);
  1554:              MainMemory.mmrM8[a + 0x00000003] = (byte) (MainMemory.mmrM8[a + 0x00000003] & x | d);
  1555:            }
  1556:            if (CRTC.crtSimPlane1) {
  1557:              MainMemory.mmrM8[a + 0x00020000] = (byte) (MainMemory.mmrM8[a + 0x00020000] & y | g);
  1558:              MainMemory.mmrM8[a + 0x00020001] = (byte) (MainMemory.mmrM8[a + 0x00020001] & x | f);
  1559:              MainMemory.mmrM8[a + 0x00020002] = (byte) (MainMemory.mmrM8[a + 0x00020002] & y | e);
  1560:              MainMemory.mmrM8[a + 0x00020003] = (byte) (MainMemory.mmrM8[a + 0x00020003] & x | d);
  1561:            }
  1562:            if (CRTC.crtSimPlane2) {
  1563:              MainMemory.mmrM8[a + 0x00040000] = (byte) (MainMemory.mmrM8[a + 0x00040000] & y | g);
  1564:              MainMemory.mmrM8[a + 0x00040001] = (byte) (MainMemory.mmrM8[a + 0x00040001] & x | f);
  1565:              MainMemory.mmrM8[a + 0x00040002] = (byte) (MainMemory.mmrM8[a + 0x00040002] & y | e);
  1566:              MainMemory.mmrM8[a + 0x00040003] = (byte) (MainMemory.mmrM8[a + 0x00040003] & x | d);
  1567:            }
  1568:            if (CRTC.crtSimPlane3) {
  1569:              MainMemory.mmrM8[a + 0x00060000] = (byte) (MainMemory.mmrM8[a + 0x00060000] & y | g);
  1570:              MainMemory.mmrM8[a + 0x00060001] = (byte) (MainMemory.mmrM8[a + 0x00060001] & x | f);
  1571:              MainMemory.mmrM8[a + 0x00060002] = (byte) (MainMemory.mmrM8[a + 0x00060002] & y | e);
  1572:              MainMemory.mmrM8[a + 0x00060003] = (byte) (MainMemory.mmrM8[a + 0x00060003] & x | d);
  1573:            }
  1574:          } else {  //同時アクセスあり,ビットマスクなし
  1575:            g = d >> 24;
  1576:            f = d >> 16;
  1577:            e = d >>  8;
  1578:            if (CRTC.crtSimPlane0) {
  1579:              MainMemory.mmrM8[a             ] = (byte) g;
  1580:              MainMemory.mmrM8[a + 0x00000001] = (byte) f;
  1581:              MainMemory.mmrM8[a + 0x00000002] = (byte) e;
  1582:              MainMemory.mmrM8[a + 0x00000003] = (byte) d;
  1583:            }
  1584:            if (CRTC.crtSimPlane1) {
  1585:              MainMemory.mmrM8[a + 0x00020000] = (byte) g;
  1586:              MainMemory.mmrM8[a + 0x00020001] = (byte) f;
  1587:              MainMemory.mmrM8[a + 0x00020002] = (byte) e;
  1588:              MainMemory.mmrM8[a + 0x00020003] = (byte) d;
  1589:            }
  1590:            if (CRTC.crtSimPlane2) {
  1591:              MainMemory.mmrM8[a + 0x00040000] = (byte) g;
  1592:              MainMemory.mmrM8[a + 0x00040001] = (byte) f;
  1593:              MainMemory.mmrM8[a + 0x00040002] = (byte) e;
  1594:              MainMemory.mmrM8[a + 0x00040003] = (byte) d;
  1595:            }
  1596:            if (CRTC.crtSimPlane3) {
  1597:              MainMemory.mmrM8[a + 0x00060000] = (byte) g;
  1598:              MainMemory.mmrM8[a + 0x00060001] = (byte) f;
  1599:              MainMemory.mmrM8[a + 0x00060002] = (byte) e;
  1600:              MainMemory.mmrM8[a + 0x00060003] = (byte) d;
  1601:            }
  1602:          }
  1603:        } else if (CRTC.crtBitMask) {  //同時アクセスなし,ビットマスクあり
  1604:          y = (x = CRTC.crtR23Mask) >> 8;
  1605:          MainMemory.mmrM8[a    ] = (byte) (MainMemory.mmrM8[a    ] & y | (d >> 24) & ~y);
  1606:          MainMemory.mmrM8[a + 1] = (byte) (MainMemory.mmrM8[a + 1] & x | (d >> 16) & ~x);
  1607:          MainMemory.mmrM8[a + 2] = (byte) (MainMemory.mmrM8[a + 1] & y | (d >>  8) & ~y);
  1608:          MainMemory.mmrM8[a + 3] = (byte) (MainMemory.mmrM8[a + 1] & x |  d        & ~x);
  1609:        } else {  //同時アクセスなし,ビットマスクなし
  1610:          if (MainMemory.MMR_USE_BYTE_BUFFER) {
  1611:            MainMemory.mmrBuffer.putInt (a, d);
  1612:          } else {
  1613:            MainMemory.mmrM8[a    ] = (byte) (d >> 24);
  1614:            MainMemory.mmrM8[a + 1] = (byte) (d >> 16);
  1615:            MainMemory.mmrM8[a + 2] = (byte) (d >>  8);
  1616:            MainMemory.mmrM8[a + 3] = (byte)  d;
  1617:          }
  1618:        }
  1619:        CRTC.crtRasterStamp[((a     & 0x0001ffff) >> 7) - CRTC.crtR11TxYCurr & 1023] = 0;  //同時アクセスやビットマスクで1ピクセルも書き換えなくても更新することになる
  1620:        CRTC.crtRasterStamp[((a + 2 & 0x0001ffff) >> 7) - CRTC.crtR11TxYCurr & 1023] = 0;  //同時アクセスやビットマスクで1ピクセルも書き換えなくても更新することになる
  1621:      }  //mmdWl
  1622:   },  //MMD_TXT
  1623: 
  1624:   //--------------------------------------------------------------------------------
  1625:   //MMD_CRT CRTコントローラ
  1626:   MMD_CRT {
  1627:     @Override public String toString () {
  1628:       return Multilingual.mlnJapanese ? "CRT コントローラ" : "CRT Controller";
  1629:     }
  1630:     //リード
  1631:     @Override protected int mmdRbz (int a) throws M68kException {
  1632:        a &= XEiJ.BUS_MOTHER_MASK;
  1633:        switch (a) {
  1634:        case CRTC.CRT_R00_HFRONT_END:  //R00の上位
  1635:        case CRTC.CRT_R01_HSYNC_END:  //R01の上位
  1636:        case CRTC.CRT_R02_HBACK_END:  //R02の上位
  1637:        case CRTC.CRT_R03_HDISP_END:  //R03の上位
  1638:        case CRTC.CRT_R08_ADJUST:  //R08の上位
  1639:        case CRTC.CRT_R24:  //R24の上位
  1640:        case CRTC.CRT_R24 + 1:  //R24の下位
  1641:        case CRTC.CRT_ACTION:  //動作ポートの上位
  1642:          return 0;
  1643:        case CRTC.CRT_R00_HFRONT_END + 1:  //R00の下位
  1644:          return CRTC.crtR00HFrontEndPort;
  1645:        case CRTC.CRT_R01_HSYNC_END + 1:  //R01の下位
  1646:          return CRTC.crtR01HSyncEndPort;
  1647:        case CRTC.CRT_R02_HBACK_END + 1:  //R02の下位
  1648:          return CRTC.crtR02HBackEndPort;
  1649:        case CRTC.CRT_R03_HDISP_END + 1:  //R03の下位
  1650:          return CRTC.crtR03HDispEndPort;
  1651:        case CRTC.CRT_R04_VFRONT_END:  //R04の上位
  1652:          return CRTC.crtR04VFrontEndPort >> 8;
  1653:        case CRTC.CRT_R04_VFRONT_END + 1:  //R04の下位
  1654:          return CRTC.crtR04VFrontEndPort & 255;
  1655:        case CRTC.CRT_R05_VSYNC_END:  //R05の上位
  1656:          return CRTC.crtR05VSyncEndPort >> 8;
  1657:        case CRTC.CRT_R05_VSYNC_END + 1:  //R05の下位
  1658:          return CRTC.crtR05VSyncEndPort & 255;
  1659:        case CRTC.CRT_R06_VBACK_END:  //R06の上位
  1660:          return CRTC.crtR06VBackEndPort >> 8;
  1661:        case CRTC.CRT_R06_VBACK_END + 1:  //R06の下位
  1662:          return CRTC.crtR06VBackEndPort & 255;
  1663:        case CRTC.CRT_R07_VDISP_END:  //R07の上位
  1664:          return CRTC.crtR07VDispEndPort >> 8;
  1665:        case CRTC.CRT_R07_VDISP_END + 1:  //R07の下位
  1666:          return CRTC.crtR07VDispEndPort & 255;
  1667:        case CRTC.CRT_R08_ADJUST + 1:  //R08の下位
  1668:          return CRTC.crtR08Adjust;
  1669:        case CRTC.CRT_R09_IRQ_RASTER:  //R09の上位
  1670:          return CRTC.crtR09IRQRasterPort >> 8;
  1671:        case CRTC.CRT_R09_IRQ_RASTER + 1:  //R09の下位
  1672:          return CRTC.crtR09IRQRasterPort & 255;
  1673:        case CRTC.CRT_R10_TX_X:  //R10の上位
  1674:          return CRTC.crtR10TxXPort >> 8;
  1675:        case CRTC.CRT_R10_TX_X + 1:  //R10の下位
  1676:          return CRTC.crtR10TxXPort & 255;
  1677:        case CRTC.CRT_R11_TX_Y:  //R11の上位
  1678:          return CRTC.crtR11TxYCurr >> 8;
  1679:        case CRTC.CRT_R11_TX_Y + 1:  //R11の下位
  1680:          return CRTC.crtR11TxYCurr & 255;
  1681:        case CRTC.CRT_R12_GR_X_0:  //R12の上位
  1682:          return CRTC.crtR12GrXPort[0] >> 8;
  1683:        case CRTC.CRT_R12_GR_X_0 + 1:  //R12の下位
  1684:          return CRTC.crtR12GrXPort[0] & 255;
  1685:        case CRTC.CRT_R13_GR_Y_0:  //R13の上位
  1686:          return CRTC.crtR13GrYPort[0] >> 8;
  1687:        case CRTC.CRT_R13_GR_Y_0 + 1:  //R13の下位
  1688:          return CRTC.crtR13GrYPort[0] & 255;
  1689:        case CRTC.CRT_R14_GR_X_1:  //R14の上位
  1690:          return CRTC.crtR12GrXPort[1] >> 8;
  1691:        case CRTC.CRT_R14_GR_X_1 + 1:  //R14の下位
  1692:          return CRTC.crtR12GrXPort[1] & 255;
  1693:        case CRTC.CRT_R15_GR_Y_1:  //R15の上位
  1694:          return CRTC.crtR13GrYPort[1] >> 8;
  1695:        case CRTC.CRT_R15_GR_Y_1 + 1:  //R15の下位
  1696:          return CRTC.crtR13GrYPort[1] & 255;
  1697:        case CRTC.CRT_R16_GR_X_2:  //R16の上位
  1698:          return CRTC.crtR12GrXPort[2] >> 8;
  1699:        case CRTC.CRT_R16_GR_X_2 + 1:  //R16の下位
  1700:          return CRTC.crtR12GrXPort[2] & 255;
  1701:        case CRTC.CRT_R17_GR_Y_2:  //R17の上位
  1702:          return CRTC.crtR13GrYPort[2] >> 8;
  1703:        case CRTC.CRT_R17_GR_Y_2 + 1:  //R17の下位
  1704:          return CRTC.crtR13GrYPort[2] & 255;
  1705:        case CRTC.CRT_R18_GR_X_3:  //R18の上位
  1706:          return CRTC.crtR12GrXPort[3] >> 8;
  1707:        case CRTC.CRT_R18_GR_X_3 + 1:  //R18の下位
  1708:          return CRTC.crtR12GrXPort[3] & 255;
  1709:        case CRTC.CRT_R19_GR_Y_3:  //R19の上位
  1710:          return CRTC.crtR13GrYPort[3] >> 8;
  1711:        case CRTC.CRT_R19_GR_Y_3 + 1:  //R19の下位
  1712:          return CRTC.crtR13GrYPort[3] & 255;
  1713:        case CRTC.CRT_R20_MODE:  //R20の上位
  1714:          return CRTC.crtMemoryModePort;
  1715:        case CRTC.CRT_R20_MODE + 1:  //R20の下位
  1716:          return CRTC.crtHighResoPort << 4 | CRTC.crtVResoPort << 2 | CRTC.crtHResoPort;
  1717:        case CRTC.CRT_R21_SELECT:  //R21の上位
  1718:          return ((CRTC.crtBitMask   ? 0b00000010 : 0) |
  1719:                  (CRTC.crtSimAccess ? 0b00000001 : 0));
  1720:        case CRTC.CRT_R21_SELECT + 1:  //R21の下位
  1721:          return ((CRTC.crtSimPlane3 ? 0b10000000 : 0) |
  1722:                  (CRTC.crtSimPlane2 ? 0b01000000 : 0) |
  1723:                  (CRTC.crtSimPlane1 ? 0b00100000 : 0) |
  1724:                  (CRTC.crtSimPlane0 ? 0b00010000 : 0) |
  1725:                  (CRTC.crtCCPlane3  ? 0b00001000 : 0) |
  1726:                  (CRTC.crtCCPlane2  ? 0b00000100 : 0) |
  1727:                  (CRTC.crtCCPlane1  ? 0b00000010 : 0) |
  1728:                  (CRTC.crtCCPlane0  ? 0b00000001 : 0));
  1729:        case CRTC.CRT_R22_BLOCK:  //R22の上位
  1730:          return CRTC.crtR22SrcBlock;
  1731:        case CRTC.CRT_R22_BLOCK + 1:  //R22の下位
  1732:          return CRTC.crtR22DstBlock;
  1733:        case CRTC.CRT_R23_MASK:  //R23の上位
  1734:          return CRTC.crtR23Mask >> 8;
  1735:        case CRTC.CRT_R23_MASK + 1:  //R23の下位
  1736:          return CRTC.crtR23Mask & 255;
  1737:        case CRTC.CRT_ACTION + 1:  //動作ポートの下位
  1738:          return ((CRTC.crtRasterCopyOn ? 8 : 0) |  //ラスタコピー
  1739:                  (CRTC.crtClearStandby || CRTC.crtClearFrames != 0 ? 2 : 0));  //高速クリア
  1740:        case 0x00e8003c:
  1741:          return VideoController.vcnMode.ordinal () >> 8;
  1742:        case 0x00e8003d:
  1743:          return VideoController.vcnMode.ordinal () & 255;
  1744:        }
  1745:        return super.mmdRbz (a);  //バスエラー
  1746:      }  //mmdRbz
  1747:     @Override protected int mmdRwz (int a) throws M68kException {
  1748:        a &= XEiJ.BUS_MOTHER_MASK;
  1749:        switch (a) {
  1750:        case CRTC.CRT_R00_HFRONT_END:  //R00
  1751:          return CRTC.crtR00HFrontEndPort;
  1752:        case CRTC.CRT_R01_HSYNC_END:  //R01
  1753:          return CRTC.crtR01HSyncEndPort;
  1754:        case CRTC.CRT_R02_HBACK_END:  //R02
  1755:          return CRTC.crtR02HBackEndPort;
  1756:        case CRTC.CRT_R03_HDISP_END:  //R03
  1757:          return CRTC.crtR03HDispEndPort;
  1758:        case CRTC.CRT_R04_VFRONT_END:  //R04
  1759:          return CRTC.crtR04VFrontEndPort;
  1760:        case CRTC.CRT_R05_VSYNC_END:  //R05
  1761:          return CRTC.crtR05VSyncEndPort;
  1762:        case CRTC.CRT_R06_VBACK_END:  //R06
  1763:          return CRTC.crtR06VBackEndPort;
  1764:        case CRTC.CRT_R07_VDISP_END:  //R07
  1765:          return CRTC.crtR07VDispEndPort;
  1766:        case CRTC.CRT_R08_ADJUST:  //R08
  1767:          return CRTC.crtR08Adjust;
  1768:        case CRTC.CRT_R09_IRQ_RASTER:  //R09
  1769:          return CRTC.crtR09IRQRasterPort;
  1770:        case CRTC.CRT_R10_TX_X:  //R10
  1771:          return CRTC.crtR10TxXPort;
  1772:        case CRTC.CRT_R11_TX_Y:  //R11
  1773:          return CRTC.crtR11TxYPort;
  1774:        case CRTC.CRT_R12_GR_X_0:  //R12
  1775:          return CRTC.crtR12GrXPort[0];
  1776:        case CRTC.CRT_R13_GR_Y_0:  //R13
  1777:          return CRTC.crtR13GrYPort[0];
  1778:        case CRTC.CRT_R14_GR_X_1:  //R14
  1779:          return CRTC.crtR12GrXPort[1];
  1780:        case CRTC.CRT_R15_GR_Y_1:  //R15
  1781:          return CRTC.crtR13GrYPort[1];
  1782:        case CRTC.CRT_R16_GR_X_2:  //R16
  1783:          return CRTC.crtR12GrXPort[2];
  1784:        case CRTC.CRT_R17_GR_Y_2:  //R17
  1785:          return CRTC.crtR13GrYPort[2];
  1786:        case CRTC.CRT_R18_GR_X_3:  //R18
  1787:          return CRTC.crtR12GrXPort[3];
  1788:        case CRTC.CRT_R19_GR_Y_3:  //R19
  1789:          return CRTC.crtR13GrYPort[3];
  1790:        case CRTC.CRT_R20_MODE:  //R20
  1791:          return CRTC.crtMemoryModePort << 8 | CRTC.crtHighResoPort << 4 | CRTC.crtVResoPort << 2 | CRTC.crtHResoPort;
  1792:        case CRTC.CRT_R21_SELECT:  //R21
  1793:          return ((CRTC.crtBitMask   ? 0b00000010_00000000 : 0) |
  1794:                  (CRTC.crtSimAccess ? 0b00000001_00000000 : 0) |
  1795:                  (CRTC.crtSimPlane3 ? 0b00000000_10000000 : 0) |
  1796:                  (CRTC.crtSimPlane2 ? 0b00000000_01000000 : 0) |
  1797:                  (CRTC.crtSimPlane1 ? 0b00000000_00100000 : 0) |
  1798:                  (CRTC.crtSimPlane0 ? 0b00000000_00010000 : 0) |
  1799:                  (CRTC.crtCCPlane3  ? 0b00000000_00001000 : 0) |
  1800:                  (CRTC.crtCCPlane2  ? 0b00000000_00000100 : 0) |
  1801:                  (CRTC.crtCCPlane1  ? 0b00000000_00000010 : 0) |
  1802:                  (CRTC.crtCCPlane0  ? 0b00000000_00000001 : 0));
  1803:        case CRTC.CRT_R22_BLOCK:  //R22
  1804:          return CRTC.crtR22SrcBlock << 8 | CRTC.crtR22DstBlock;
  1805:        case CRTC.CRT_R23_MASK:  //R23
  1806:          return CRTC.crtR23Mask;
  1807:        case CRTC.CRT_R24:  //R24
  1808:          return 0;
  1809:        case CRTC.CRT_ACTION:  //動作ポート
  1810:          return ((CRTC.crtRasterCopyOn ? 8 : 0) |  //ラスタコピー
  1811:                  (CRTC.crtClearStandby || CRTC.crtClearFrames != 0 ? 2 : 0));  //高速クリア
  1812:        }
  1813:        return super.mmdRwz (a);  //バスエラー
  1814:      }  //mmdRwz
  1815:     @Override protected int mmdRls (int a) throws M68kException {
  1816:        a &= XEiJ.BUS_MOTHER_MASK;
  1817:        return mmdRwz (a) << 16 | mmdRwz (a + 2);
  1818:      }
  1819:     //ライト
  1820:     @Override protected void mmdWb (int a, int d) throws M68kException {
  1821:        a &= XEiJ.BUS_MOTHER_MASK;
  1822:        switch (a) {
  1823:        case CRTC.CRT_R00_HFRONT_END:  //R00の上位
  1824:          return;
  1825:        case CRTC.CRT_R00_HFRONT_END + 1:  //R00の下位
  1826:          CRTC.crtR00HFrontEndPort = d & 255;
  1827:          {
  1828:            int curr = CRTC.crtR00HFrontEndMask == 0 ? CRTC.crtR00HFrontEndPort : CRTC.crtR00HFrontEndTest;
  1829:            if (CRTC.crtR00HFrontEndCurr != curr) {
  1830:              CRTC.crtR00HFrontEndCurr = curr;
  1831:              CRTC.crtRestart ();
  1832:            }
  1833:          }
  1834:          return;
  1835:        case CRTC.CRT_R01_HSYNC_END:  //R01の上位
  1836:          return;
  1837:        case CRTC.CRT_R01_HSYNC_END + 1:  //R01の下位
  1838:          CRTC.crtR01HSyncEndPort = d & 255;
  1839:          {
  1840:            int curr = CRTC.crtR01HSyncEndMask == 0 ? CRTC.crtR01HSyncEndPort : CRTC.crtR01HSyncEndTest;
  1841:            if (CRTC.crtR01HSyncEndCurr != curr) {
  1842:              CRTC.crtR01HSyncEndCurr = curr;
  1843:              CRTC.crtRestart ();
  1844:            }
  1845:          }
  1846:          return;
  1847:        case CRTC.CRT_R02_HBACK_END:  //R02の上位
  1848:          return;
  1849:        case CRTC.CRT_R02_HBACK_END + 1:  //R02の下位
  1850:          CRTC.crtR02HBackEndPort = d & 255;
  1851:          {
  1852:            int curr = CRTC.crtR02HBackEndMask == 0 ? CRTC.crtR02HBackEndPort : CRTC.crtR02HBackEndTest;
  1853:            if (CRTC.crtR02HBackEndCurr != curr) {
  1854:              CRTC.crtR02HBackEndCurr = curr;
  1855:              CRTC.crtRestart ();
  1856:            }
  1857:          }
  1858:          return;
  1859:        case CRTC.CRT_R03_HDISP_END:  //R03の上位
  1860:          return;
  1861:        case CRTC.CRT_R03_HDISP_END + 1:  //R03の下位
  1862:          CRTC.crtR03HDispEndPort = d & 255;
  1863:          {
  1864:            int curr = CRTC.crtR03HDispEndMask == 0 ? CRTC.crtR03HDispEndPort : CRTC.crtR03HDispEndTest;
  1865:            if (CRTC.crtR03HDispEndCurr != curr) {
  1866:              CRTC.crtR03HDispEndCurr = curr;
  1867:              CRTC.crtRestart ();
  1868:            }
  1869:          }
  1870:          return;
  1871:        case CRTC.CRT_R04_VFRONT_END:  //R04の上位
  1872:          CRTC.crtR04VFrontEndPort = (d & 3) << 8 | CRTC.crtR04VFrontEndPort & 255;
  1873:          {
  1874:            int curr = CRTC.crtR04VFrontEndMask == 0 ? CRTC.crtR04VFrontEndPort : CRTC.crtR04VFrontEndTest;
  1875:            if (CRTC.crtR04VFrontEndCurr != curr) {
  1876:              CRTC.crtR04VFrontEndCurr = curr;
  1877:              if (CRTC.CRT_RASTER_HASH_ON) {
  1878:                CRTC.crtUpdateRasterHash ();
  1879:              }
  1880:              CRTC.crtRestart ();
  1881:            }
  1882:          }
  1883:          return;
  1884:        case CRTC.CRT_R04_VFRONT_END + 1:  //R04の下位
  1885:          CRTC.crtR04VFrontEndPort = CRTC.crtR04VFrontEndPort & 3 << 8 | d & 255;
  1886:          {
  1887:            int curr = CRTC.crtR04VFrontEndMask == 0 ? CRTC.crtR04VFrontEndPort : CRTC.crtR04VFrontEndTest;
  1888:            if (CRTC.crtR04VFrontEndCurr != curr) {
  1889:              CRTC.crtR04VFrontEndCurr = curr;
  1890:              if (CRTC.CRT_RASTER_HASH_ON) {
  1891:                CRTC.crtUpdateRasterHash ();
  1892:              }
  1893:              CRTC.crtRestart ();
  1894:            }
  1895:          }
  1896:          return;
  1897:        case CRTC.CRT_R05_VSYNC_END:  //R05の上位
  1898:          CRTC.crtR05VSyncEndPort = (d & 3) << 8 | CRTC.crtR05VSyncEndPort & 255;
  1899:          {
  1900:            int curr = CRTC.crtR05VSyncEndMask == 0 ? CRTC.crtR05VSyncEndPort : CRTC.crtR05VSyncEndTest;
  1901:            if (CRTC.crtR05VSyncEndCurr != curr) {
  1902:              CRTC.crtR05VSyncEndCurr = curr;
  1903:              CRTC.crtRestart ();
  1904:            }
  1905:          }
  1906:          return;
  1907:        case CRTC.CRT_R05_VSYNC_END + 1:  //R05の下位
  1908:          CRTC.crtR05VSyncEndPort = CRTC.crtR05VSyncEndPort & 3 << 8 | d & 255;
  1909:          {
  1910:            int curr = CRTC.crtR05VSyncEndMask == 0 ? CRTC.crtR05VSyncEndPort : CRTC.crtR05VSyncEndTest;
  1911:            if (CRTC.crtR05VSyncEndCurr != curr) {
  1912:              CRTC.crtR05VSyncEndCurr = curr;
  1913:              CRTC.crtRestart ();
  1914:            }
  1915:          }
  1916:          return;
  1917:        case CRTC.CRT_R06_VBACK_END:  //R06の上位
  1918:          CRTC.crtR06VBackEndPort = (d & 3) << 8 | CRTC.crtR06VBackEndPort & 255;
  1919:          {
  1920:            int curr = CRTC.crtR06VBackEndMask == 0 ? CRTC.crtR06VBackEndPort : CRTC.crtR06VBackEndTest;
  1921:            if (CRTC.crtR06VBackEndCurr != curr) {
  1922:              CRTC.crtR06VBackEndCurr = curr;
  1923:              CRTC.crtVDispStart = curr + 1;
  1924:              if (CRTC.CRT_RASTER_HASH_ON) {
  1925:                CRTC.crtUpdateRasterHash ();
  1926:              }
  1927:              CRTC.crtRestart ();
  1928:            }
  1929:          }
  1930:          return;
  1931:        case CRTC.CRT_R06_VBACK_END + 1:  //R06の下位
  1932:          CRTC.crtR06VBackEndPort = CRTC.crtR06VBackEndPort & 3 << 8 | d & 255;
  1933:          {
  1934:            int curr = CRTC.crtR06VBackEndMask == 0 ? CRTC.crtR06VBackEndPort : CRTC.crtR06VBackEndTest;
  1935:            if (CRTC.crtR06VBackEndCurr != curr) {
  1936:              CRTC.crtR06VBackEndCurr = curr;
  1937:              CRTC.crtVDispStart = curr + 1;
  1938:              if (CRTC.CRT_RASTER_HASH_ON) {
  1939:                CRTC.crtUpdateRasterHash ();
  1940:              }
  1941:              CRTC.crtRestart ();
  1942:            }
  1943:          }
  1944:          return;
  1945:        case CRTC.CRT_R07_VDISP_END:  //R07の上位
  1946:          CRTC.crtR07VDispEndPort = (d & 3) << 8 | CRTC.crtR07VDispEndPort & 255;
  1947:          {
  1948:            int curr = CRTC.crtR07VDispEndMask == 0 ? CRTC.crtR07VDispEndPort : CRTC.crtR07VDispEndTest;
  1949:            if (CRTC.crtR07VDispEndCurr != curr) {
  1950:              CRTC.crtR07VDispEndCurr = curr;
  1951:              CRTC.crtVIdleStart = curr + 1;
  1952:              if (CRTC.CRT_RASTER_HASH_ON) {
  1953:                CRTC.crtUpdateRasterHash ();
  1954:              }
  1955:              CRTC.crtRestart ();
  1956:            }
  1957:          }
  1958:          return;
  1959:        case CRTC.CRT_R07_VDISP_END + 1:  //R07の下位
  1960:          CRTC.crtR07VDispEndPort = CRTC.crtR07VDispEndPort & 3 << 8 | d & 255;
  1961:          {
  1962:            int curr = CRTC.crtR07VDispEndMask == 0 ? CRTC.crtR07VDispEndPort : CRTC.crtR07VDispEndTest;
  1963:            if (CRTC.crtR07VDispEndCurr != curr) {
  1964:              CRTC.crtR07VDispEndCurr = curr;
  1965:              CRTC.crtVIdleStart = curr + 1;
  1966:              if (CRTC.CRT_RASTER_HASH_ON) {
  1967:                CRTC.crtUpdateRasterHash ();
  1968:              }
  1969:              CRTC.crtRestart ();
  1970:            }
  1971:          }
  1972:          return;
  1973:        case CRTC.CRT_R08_ADJUST:  //R08の上位
  1974:          return;
  1975:        case CRTC.CRT_R08_ADJUST + 1:  //R08の下位
  1976:          d &= 0xff;
  1977:          if (CRTC.crtR08Adjust != d) {
  1978:            CRTC.crtR08Adjust = d;
  1979:            CRTC.crtRestart ();
  1980:          }
  1981:          return;
  1982:        case CRTC.CRT_R09_IRQ_RASTER:  //R09の上位
  1983:          CRTC.crtR09IRQRasterPort = (d & 3) << 8 | CRTC.crtR09IRQRasterPort & 255;
  1984:          {
  1985:            int curr = CRTC.crtR09IRQRasterMask == 0 ? CRTC.crtR09IRQRasterPort : CRTC.crtR09IRQRasterTest;
  1986:            if (CRTC.crtR09IRQRasterCurr != curr) {
  1987:              CRTC.crtR09IRQRasterCurr = curr;
  1988:              if (CRTC.CRT_RASTER_HASH_ON) {
  1989:                CRTC.crtUpdateRasterHash ();
  1990:              }
  1991:              if (RasterBreakPoint.RBP_ON) {
  1992:                RasterBreakPoint.rbpCheckIRQ ();
  1993:              }
  1994:            }
  1995:          }
  1996:          return;
  1997:        case CRTC.CRT_R09_IRQ_RASTER + 1:  //R09の下位
  1998:          CRTC.crtR09IRQRasterPort = CRTC.crtR09IRQRasterPort & 3 << 8 | d & 255;
  1999:          {
  2000:            int curr = CRTC.crtR09IRQRasterMask == 0 ? CRTC.crtR09IRQRasterPort : CRTC.crtR09IRQRasterTest;
  2001:            if (CRTC.crtR09IRQRasterCurr != curr) {
  2002:              CRTC.crtR09IRQRasterCurr = curr;
  2003:              if (CRTC.CRT_RASTER_HASH_ON) {
  2004:                CRTC.crtUpdateRasterHash ();
  2005:              }
  2006:              if (RasterBreakPoint.RBP_ON) {
  2007:                RasterBreakPoint.rbpCheckIRQ ();
  2008:              }
  2009:            }
  2010:          }
  2011:          return;
  2012:        case CRTC.CRT_R10_TX_X:  //R10の上位
  2013:          CRTC.crtR10TxXPort = (d & 3) << 8 | CRTC.crtR10TxXPort & 255;
  2014:          {
  2015:            int curr = CRTC.crtR10TxXMask == 0 ? CRTC.crtR10TxXPort : CRTC.crtR10TxXTest;
  2016:            if (CRTC.crtR10TxXCurr != curr) {
  2017:              CRTC.crtR10TxXCurr = curr;
  2018:              CRTC.crtAllStamp += 2;
  2019:            }
  2020:          }
  2021:          return;
  2022:        case CRTC.CRT_R10_TX_X + 1:  //R10の下位
  2023:          CRTC.crtR10TxXPort = CRTC.crtR10TxXPort & 3 << 8 | d & 255;
  2024:          {
  2025:            int curr = CRTC.crtR10TxXMask == 0 ? CRTC.crtR10TxXPort : CRTC.crtR10TxXTest;
  2026:            if (CRTC.crtR10TxXCurr != curr) {
  2027:              CRTC.crtR10TxXCurr = curr;
  2028:              CRTC.crtAllStamp += 2;
  2029:            }
  2030:          }
  2031:          return;
  2032:        case CRTC.CRT_R11_TX_Y:  //R11の上位
  2033:          CRTC.crtR11TxYPort = (d & 3) << 8 | CRTC.crtR11TxYPort & 255;
  2034:          {
  2035:            int curr = CRTC.crtR11TxYMask == 0 ? CRTC.crtR11TxYPort : CRTC.crtR11TxYTest;
  2036:            if (CRTC.crtR11TxYCurr != curr) {
  2037:              CRTC.crtR11TxYCurr = curr;
  2038:              CRTC.crtAllStamp += 2;
  2039:            }
  2040:          }
  2041:          return;
  2042:        case CRTC.CRT_R11_TX_Y + 1:  //R11の下位
  2043:          CRTC.crtR11TxYPort = CRTC.crtR11TxYPort & 3 << 8 | d & 255;
  2044:          {
  2045:            int curr = CRTC.crtR11TxYMask == 0 ? CRTC.crtR11TxYPort : CRTC.crtR11TxYTest;
  2046:            if (CRTC.crtR11TxYCurr != curr) {
  2047:              CRTC.crtR11TxYCurr = curr;
  2048:              CRTC.crtAllStamp += 2;
  2049:            }
  2050:          }
  2051:          return;
  2052:        case CRTC.CRT_R12_GR_X_0:  //R12の上位
  2053:          CRTC.crtR12GrXPort[0] = (d & 3) << 8 | CRTC.crtR12GrXPort[0] & 255;
  2054:          {
  2055:            int curr = CRTC.crtR12GrXMask[0] == 0 ? CRTC.crtR12GrXPort[0] : CRTC.crtR12GrXTest[0];
  2056:            if (CRTC.crtR12GrXCurr[0] != curr) {
  2057:              CRTC.crtR12GrXCurr[0] = curr;
  2058:              CRTC.crtAllStamp += 2;
  2059:            }
  2060:          }
  2061:          return;
  2062:        case CRTC.CRT_R12_GR_X_0 + 1:  //R12の下位
  2063:          CRTC.crtR12GrXPort[0] = CRTC.crtR12GrXPort[0] & 3 << 8 | d & 255;
  2064:          {
  2065:            int curr = CRTC.crtR12GrXMask[0] == 0 ? CRTC.crtR12GrXPort[0] : CRTC.crtR12GrXTest[0];
  2066:            if (CRTC.crtR12GrXCurr[0] != curr) {
  2067:              CRTC.crtR12GrXCurr[0] = curr;
  2068:              CRTC.crtAllStamp += 2;
  2069:            }
  2070:          }
  2071:          return;
  2072:        case CRTC.CRT_R13_GR_Y_0:  //R13の上位
  2073:          CRTC.crtR13GrYPort[0] = (d & 3) << 8 | CRTC.crtR13GrYPort[0] & 255;
  2074:          {
  2075:            int curr = CRTC.crtR13GrYMask[0] == 0 ? CRTC.crtR13GrYPort[0] : CRTC.crtR13GrYTest[0];
  2076:            if (CRTC.crtR13GrYCurr[0] != curr) {
  2077:              CRTC.crtR13GrYCurr[0] = curr;
  2078:              CRTC.crtAllStamp += 2;
  2079:            }
  2080:          }
  2081:          return;
  2082:        case CRTC.CRT_R13_GR_Y_0 + 1:  //R13の下位
  2083:          CRTC.crtR13GrYPort[0] = CRTC.crtR13GrYPort[0] & 3 << 8 | d & 255;
  2084:          {
  2085:            int curr = CRTC.crtR13GrYMask[0] == 0 ? CRTC.crtR13GrYPort[0] : CRTC.crtR13GrYTest[0];
  2086:            if (CRTC.crtR13GrYCurr[0] != curr) {
  2087:              CRTC.crtR13GrYCurr[0] = curr;
  2088:              CRTC.crtAllStamp += 2;
  2089:            }
  2090:          }
  2091:          return;
  2092:        case CRTC.CRT_R14_GR_X_1:  //R14の上位
  2093:          CRTC.crtR12GrXPort[1] = (d & 1) << 8 | CRTC.crtR12GrXPort[1] & 255;
  2094:          {
  2095:            int curr = CRTC.crtR12GrXMask[1] == 0 ? CRTC.crtR12GrXPort[1] : CRTC.crtR12GrXTest[1];
  2096:            if (CRTC.crtR12GrXCurr[1] != curr) {
  2097:              CRTC.crtR12GrXCurr[1] = curr;
  2098:              CRTC.crtAllStamp += 2;
  2099:            }
  2100:          }
  2101:          return;
  2102:        case CRTC.CRT_R14_GR_X_1 + 1:  //R14の下位
  2103:          CRTC.crtR12GrXPort[1] = CRTC.crtR12GrXPort[1] & 1 << 8 | d & 255;
  2104:          {
  2105:            int curr = CRTC.crtR12GrXMask[1] == 0 ? CRTC.crtR12GrXPort[1] : CRTC.crtR12GrXTest[1];
  2106:            if (CRTC.crtR12GrXCurr[1] != curr) {
  2107:              CRTC.crtR12GrXCurr[1] = curr;
  2108:              CRTC.crtAllStamp += 2;
  2109:            }
  2110:          }
  2111:          return;
  2112:        case CRTC.CRT_R15_GR_Y_1:  //R15の上位
  2113:          CRTC.crtR13GrYPort[1] = (d & 1) << 8 | CRTC.crtR13GrYPort[1] & 255;
  2114:          {
  2115:            int curr = CRTC.crtR13GrYMask[1] == 0 ? CRTC.crtR13GrYPort[1] : CRTC.crtR13GrYTest[1];
  2116:            if (CRTC.crtR13GrYCurr[1] != curr) {
  2117:              CRTC.crtR13GrYCurr[1] = curr;
  2118:              CRTC.crtAllStamp += 2;
  2119:            }
  2120:          }
  2121:          return;
  2122:        case CRTC.CRT_R15_GR_Y_1 + 1:  //R15の下位
  2123:          CRTC.crtR13GrYPort[1] = CRTC.crtR13GrYPort[1] & 1 << 8 | d & 255;
  2124:          {
  2125:            int curr = CRTC.crtR13GrYMask[1] == 0 ? CRTC.crtR13GrYPort[1] : CRTC.crtR13GrYTest[1];
  2126:            if (CRTC.crtR13GrYCurr[1] != curr) {
  2127:              CRTC.crtR13GrYCurr[1] = curr;
  2128:              CRTC.crtAllStamp += 2;
  2129:            }
  2130:          }
  2131:          return;
  2132:        case CRTC.CRT_R16_GR_X_2:  //R16の上位
  2133:          CRTC.crtR12GrXPort[2] = (d & 1) << 8 | CRTC.crtR12GrXPort[2] & 255;
  2134:          {
  2135:            int curr = CRTC.crtR12GrXMask[2] == 0 ? CRTC.crtR12GrXPort[2] : CRTC.crtR12GrXTest[2];
  2136:            if (CRTC.crtR12GrXCurr[2] != curr) {
  2137:              CRTC.crtR12GrXCurr[2] = curr;
  2138:              CRTC.crtAllStamp += 2;
  2139:            }
  2140:          }
  2141:          return;
  2142:        case CRTC.CRT_R16_GR_X_2 + 1:  //R16の下位
  2143:          CRTC.crtR12GrXPort[2] = CRTC.crtR12GrXPort[2] & 1 << 8 | d & 255;
  2144:          {
  2145:            int curr = CRTC.crtR12GrXMask[2] == 0 ? CRTC.crtR12GrXPort[2] : CRTC.crtR12GrXTest[2];
  2146:            if (CRTC.crtR12GrXCurr[2] != curr) {
  2147:              CRTC.crtR12GrXCurr[2] = curr;
  2148:              CRTC.crtAllStamp += 2;
  2149:            }
  2150:          }
  2151:          return;
  2152:        case CRTC.CRT_R17_GR_Y_2:  //R17の上位
  2153:          CRTC.crtR13GrYPort[2] = (d & 1) << 8 | CRTC.crtR13GrYPort[2] & 255;
  2154:          {
  2155:            int curr = CRTC.crtR13GrYMask[2] == 0 ? CRTC.crtR13GrYPort[2] : CRTC.crtR13GrYTest[2];
  2156:            if (CRTC.crtR13GrYCurr[2] != curr) {
  2157:              CRTC.crtR13GrYCurr[2] = curr;
  2158:              CRTC.crtAllStamp += 2;
  2159:            }
  2160:          }
  2161:          return;
  2162:        case CRTC.CRT_R17_GR_Y_2 + 1:  //R17の下位
  2163:          CRTC.crtR13GrYPort[2] = CRTC.crtR13GrYPort[2] & 1 << 8 | d & 255;
  2164:          {
  2165:            int curr = CRTC.crtR13GrYMask[2] == 0 ? CRTC.crtR13GrYPort[2] : CRTC.crtR13GrYTest[2];
  2166:            if (CRTC.crtR13GrYCurr[2] != curr) {
  2167:              CRTC.crtR13GrYCurr[2] = curr;
  2168:              CRTC.crtAllStamp += 2;
  2169:            }
  2170:          }
  2171:          return;
  2172:        case CRTC.CRT_R18_GR_X_3:  //R18の上位
  2173:          CRTC.crtR12GrXPort[3] = (d & 1) << 8 | CRTC.crtR12GrXPort[3] & 255;
  2174:          {
  2175:            int curr = CRTC.crtR12GrXMask[3] == 0 ? CRTC.crtR12GrXPort[3] : CRTC.crtR12GrXTest[3];
  2176:            if (CRTC.crtR12GrXCurr[3] != curr) {
  2177:              CRTC.crtR12GrXCurr[3] = curr;
  2178:              CRTC.crtAllStamp += 2;
  2179:            }
  2180:          }
  2181:          return;
  2182:        case CRTC.CRT_R18_GR_X_3 + 1:  //R18の下位
  2183:          CRTC.crtR12GrXPort[3] = CRTC.crtR12GrXPort[3] & 1 << 8 | d & 255;
  2184:          {
  2185:            int curr = CRTC.crtR12GrXMask[3] == 0 ? CRTC.crtR12GrXPort[3] : CRTC.crtR12GrXTest[3];
  2186:            if (CRTC.crtR12GrXCurr[3] != curr) {
  2187:              CRTC.crtR12GrXCurr[3] = curr;
  2188:              CRTC.crtAllStamp += 2;
  2189:            }
  2190:          }
  2191:          return;
  2192:        case CRTC.CRT_R19_GR_Y_3:  //R19の上位
  2193:          CRTC.crtR13GrYPort[3] = (d & 1) << 8 | CRTC.crtR13GrYPort[3] & 255;
  2194:          {
  2195:            int curr = CRTC.crtR13GrYMask[3] == 0 ? CRTC.crtR13GrYPort[3] : CRTC.crtR13GrYTest[3];
  2196:            if (CRTC.crtR13GrYCurr[3] != curr) {
  2197:              CRTC.crtR13GrYCurr[3] = curr;
  2198:              CRTC.crtAllStamp += 2;
  2199:            }
  2200:          }
  2201:          return;
  2202:        case CRTC.CRT_R19_GR_Y_3 + 1:  //R19の下位
  2203:          CRTC.crtR13GrYPort[3] = CRTC.crtR13GrYPort[3] & 1 << 8 | d & 255;
  2204:          {
  2205:            int curr = CRTC.crtR13GrYMask[3] == 0 ? CRTC.crtR13GrYPort[3] : CRTC.crtR13GrYTest[3];
  2206:            if (CRTC.crtR13GrYCurr[3] != curr) {
  2207:              CRTC.crtR13GrYCurr[3] = curr;
  2208:              CRTC.crtAllStamp += 2;
  2209:            }
  2210:          }
  2211:          return;
  2212:        case CRTC.CRT_R20_MODE:  //R20の上位
  2213:          CRTC.crtSetMemoryMode (d & 7);
  2214:          return;
  2215:        case CRTC.CRT_R20_MODE + 1:  //R20の下位
  2216:          CRTC.crtHighResoPort = d >>> 4 & 1;
  2217:          CRTC.crtVResoPort    = d >>> 2 & 3;
  2218:          CRTC.crtHResoPort    = d       & 3;
  2219:          int highResoCurr = CRTC.crtHighResoMask == 0 ? CRTC.crtHighResoPort : CRTC.crtHighResoTest;
  2220:          int vResoCurr = CRTC.crtVResoMask == 0 ? CRTC.crtVResoPort : CRTC.crtVResoTest;
  2221:          int hResoCurr = CRTC.crtHResoMask == 0 ? CRTC.crtHResoPort : CRTC.crtHResoTest;
  2222:          if (CRTC.crtHighResoCurr != highResoCurr ||
  2223:              CRTC.crtVResoCurr != vResoCurr ||
  2224:              CRTC.crtHResoCurr != hResoCurr) {
  2225:            CRTC.crtHighResoCurr = highResoCurr;
  2226:            CRTC.crtVResoCurr = vResoCurr;
  2227:            CRTC.crtHResoCurr = hResoCurr;
  2228:            CRTC.crtRestart ();
  2229:          }
  2230:          return;
  2231:        case CRTC.CRT_R21_SELECT:  //R21の上位
  2232:          CRTC.crtBitMask   = XEiJ.TEST_BIT_1_SHIFT ? d << 31 - 1 < 0 : (d & 2) != 0;
  2233:          CRTC.crtSimAccess = XEiJ.TEST_BIT_0_SHIFT ? d << 31 - 0 < 0 : (d & 1) != 0;
  2234:          return;
  2235:        case CRTC.CRT_R21_SELECT + 1:  //R21の下位
  2236:          CRTC.crtSimPlane3 = (byte) d < 0;  //(d & 128) != 0。d << 24 < 0
  2237:          CRTC.crtSimPlane2 = d << 25 < 0;  //(d & 64) != 0
  2238:          CRTC.crtSimPlane1 = d << 26 < 0;  //(d & 32) != 0
  2239:          CRTC.crtSimPlane0 = d << 27 < 0;  //(d & 16) != 0
  2240:          CRTC.crtCCPlane3  = XEiJ.TEST_BIT_3_SHIFT ? d << 31 - 3 < 0 : (d & 8) != 0;
  2241:          CRTC.crtCCPlane2  = XEiJ.TEST_BIT_2_SHIFT ? d << 31 - 2 < 0 : (d & 4) != 0;
  2242:          CRTC.crtCCPlane1  = XEiJ.TEST_BIT_1_SHIFT ? d << 31 - 1 < 0 : (d & 2) != 0;
  2243:          CRTC.crtCCPlane0  = XEiJ.TEST_BIT_0_SHIFT ? d << 31 - 0 < 0 : (d & 1) != 0;
  2244:          return;
  2245:        case CRTC.CRT_R22_BLOCK:  //R22の上位
  2246:          CRTC.crtR22SrcBlock = d & 255;
  2247:          return;
  2248:        case CRTC.CRT_R22_BLOCK + 1:  //R22の下位
  2249:          CRTC.crtR22DstBlock = d & 255;
  2250:          return;
  2251:        case CRTC.CRT_R23_MASK:  //R23の上位
  2252:          CRTC.crtR23Mask = (0xff & d) << 8 | 0xff & CRTC.crtR23Mask;
  2253:          return;
  2254:        case CRTC.CRT_R23_MASK + 1:  //R23の下位
  2255:          CRTC.crtR23Mask = 0xff00 & CRTC.crtR23Mask | 0xff & d;
  2256:          return;
  2257:        case CRTC.CRT_R24:  //R24の上位
  2258:        case CRTC.CRT_R24 + 1:  //R24の下位
  2259:        case CRTC.CRT_ACTION:  //動作ポートの上位
  2260:          return;
  2261:        case CRTC.CRT_ACTION + 1:  //動作ポートの下位
  2262:          {
  2263:            boolean rasterCopyOn = (d & 8) != 0;
  2264:            if (CRTC.crtRasterCopyOn != rasterCopyOn) {
  2265:              CRTC.crtRasterCopyOn = rasterCopyOn;  //ラスタコピー
  2266:              if (CRTC.CRT_RASTER_HASH_ON) {
  2267:                CRTC.crtUpdateRasterHash ();
  2268:              }
  2269:            }
  2270:          }
  2271:          CRTC.crtClearStandby = (d & 2) != 0;  //高速クリア
  2272:          return;
  2273:        }
  2274:        super.mmdWb (a, d);  //バスエラー
  2275:      }
  2276:     @Override protected void mmdWw (int a, int d) throws M68kException {
  2277:        a &= XEiJ.BUS_MOTHER_MASK;
  2278:        switch (a) {
  2279:        case CRTC.CRT_R00_HFRONT_END:  //R00
  2280:          CRTC.crtR00HFrontEndPort = d & 255;
  2281:          {
  2282:            int curr = CRTC.crtR00HFrontEndMask == 0 ? CRTC.crtR00HFrontEndPort : CRTC.crtR00HFrontEndTest;
  2283:            if (CRTC.crtR00HFrontEndCurr != curr) {
  2284:              CRTC.crtR00HFrontEndCurr = curr;
  2285:              CRTC.crtRestart ();
  2286:            }
  2287:          }
  2288:          return;
  2289:        case CRTC.CRT_R01_HSYNC_END:  //R01
  2290:          CRTC.crtR01HSyncEndPort = d & 255;
  2291:          {
  2292:            int curr = CRTC.crtR01HSyncEndMask == 0 ? CRTC.crtR01HSyncEndPort : CRTC.crtR01HSyncEndTest;
  2293:            if (CRTC.crtR01HSyncEndCurr != curr) {
  2294:              CRTC.crtR01HSyncEndCurr = curr;
  2295:              CRTC.crtRestart ();
  2296:            }
  2297:          }
  2298:          return;
  2299:        case CRTC.CRT_R02_HBACK_END:  //R02
  2300:          CRTC.crtR02HBackEndPort = d & 255;
  2301:          {
  2302:            int curr = CRTC.crtR02HBackEndMask == 0 ? CRTC.crtR02HBackEndPort : CRTC.crtR02HBackEndTest;
  2303:            if (CRTC.crtR02HBackEndCurr != curr) {
  2304:              CRTC.crtR02HBackEndCurr = curr;
  2305:              CRTC.crtRestart ();
  2306:            }
  2307:          }
  2308:          return;
  2309:        case CRTC.CRT_R03_HDISP_END:  //R03
  2310:          CRTC.crtR03HDispEndPort = d & 255;
  2311:          {
  2312:            int curr = CRTC.crtR03HDispEndMask == 0 ? CRTC.crtR03HDispEndPort : CRTC.crtR03HDispEndTest;
  2313:            if (CRTC.crtR03HDispEndCurr != curr) {
  2314:              CRTC.crtR03HDispEndCurr = curr;
  2315:              CRTC.crtRestart ();
  2316:            }
  2317:          }
  2318:          return;
  2319:        case CRTC.CRT_R04_VFRONT_END:  //R04
  2320:          CRTC.crtR04VFrontEndPort = d & 1023;
  2321:          {
  2322:            int curr = CRTC.crtR04VFrontEndMask == 0 ? CRTC.crtR04VFrontEndPort : CRTC.crtR04VFrontEndTest;
  2323:            if (CRTC.crtR04VFrontEndCurr != curr) {
  2324:              CRTC.crtR04VFrontEndCurr = curr;
  2325:              if (CRTC.CRT_RASTER_HASH_ON) {
  2326:                CRTC.crtUpdateRasterHash ();
  2327:              }
  2328:              CRTC.crtRestart ();
  2329:            }
  2330:          }
  2331:          return;
  2332:        case CRTC.CRT_R05_VSYNC_END:  //R05
  2333:          CRTC.crtR05VSyncEndPort = d & 1023;
  2334:          {
  2335:            int curr = CRTC.crtR05VSyncEndMask == 0 ? CRTC.crtR05VSyncEndPort : CRTC.crtR05VSyncEndTest;
  2336:            if (CRTC.crtR05VSyncEndCurr != curr) {
  2337:              CRTC.crtR05VSyncEndCurr = curr;
  2338:              CRTC.crtRestart ();
  2339:            }
  2340:          }
  2341:          return;
  2342:        case CRTC.CRT_R06_VBACK_END:  //R06
  2343:          CRTC.crtR06VBackEndPort = d & 1023;
  2344:          {
  2345:            int curr = CRTC.crtR06VBackEndMask == 0 ? CRTC.crtR06VBackEndPort : CRTC.crtR06VBackEndTest;
  2346:            if (CRTC.crtR06VBackEndCurr != curr) {
  2347:              CRTC.crtR06VBackEndCurr = curr;
  2348:              CRTC.crtVDispStart = curr + 1;
  2349:              if (CRTC.CRT_RASTER_HASH_ON) {
  2350:                CRTC.crtUpdateRasterHash ();
  2351:              }
  2352:              CRTC.crtRestart ();
  2353:            }
  2354:          }
  2355:          return;
  2356:        case CRTC.CRT_R07_VDISP_END:  //R07
  2357:          CRTC.crtR07VDispEndPort = d & 1023;
  2358:          {
  2359:            int curr = CRTC.crtR07VDispEndMask == 0 ? CRTC.crtR07VDispEndPort : CRTC.crtR07VDispEndTest;
  2360:            if (CRTC.crtR07VDispEndCurr != curr) {
  2361:              CRTC.crtR07VDispEndCurr = curr;
  2362:              CRTC.crtVIdleStart = curr + 1;
  2363:              if (CRTC.CRT_RASTER_HASH_ON) {
  2364:                CRTC.crtUpdateRasterHash ();
  2365:              }
  2366:              CRTC.crtRestart ();
  2367:            }
  2368:          }
  2369:          return;
  2370:        case CRTC.CRT_R08_ADJUST:  //R08
  2371:          d &= 0x00ff;
  2372:          if (CRTC.crtR08Adjust != d) {
  2373:            CRTC.crtR08Adjust = d;
  2374:            CRTC.crtRestart ();
  2375:          }
  2376:          return;
  2377:        case CRTC.CRT_R09_IRQ_RASTER:  //R09
  2378:          CRTC.crtR09IRQRasterPort = d & 1023;
  2379:          {
  2380:            int curr = CRTC.crtR09IRQRasterMask == 0 ? CRTC.crtR09IRQRasterPort : CRTC.crtR09IRQRasterTest;
  2381:            if (CRTC.crtR09IRQRasterCurr != curr) {
  2382:              CRTC.crtR09IRQRasterCurr = curr;
  2383:              if (CRTC.CRT_RASTER_HASH_ON) {
  2384:                CRTC.crtUpdateRasterHash ();
  2385:              }
  2386:              if (RasterBreakPoint.RBP_ON) {
  2387:                RasterBreakPoint.rbpCheckIRQ ();
  2388:              }
  2389:            }
  2390:          }
  2391:          return;
  2392:        case CRTC.CRT_R10_TX_X:  //R10
  2393:          CRTC.crtR10TxXPort = d & 1023;
  2394:          {
  2395:            int curr = CRTC.crtR10TxXMask == 0 ? CRTC.crtR10TxXPort : CRTC.crtR10TxXTest;
  2396:            if (CRTC.crtR10TxXCurr != curr) {
  2397:              CRTC.crtR10TxXCurr = curr;
  2398:              CRTC.crtAllStamp += 2;
  2399:            }
  2400:          }
  2401:          return;
  2402:        case CRTC.CRT_R11_TX_Y:  //R11
  2403:          CRTC.crtR11TxYPort = d & 1023;
  2404:          {
  2405:            int curr = CRTC.crtR11TxYMask == 0 ? CRTC.crtR11TxYPort : CRTC.crtR11TxYTest;
  2406:            if (CRTC.crtR11TxYCurr != curr) {
  2407:              CRTC.crtR11TxYCurr = curr;
  2408:              CRTC.crtAllStamp += 2;
  2409:            }
  2410:          }
  2411:          return;
  2412:        case CRTC.CRT_R12_GR_X_0:  //R12
  2413:          CRTC.crtR12GrXPort[0] = d & 1023;
  2414:          {
  2415:            int curr = CRTC.crtR12GrXMask[0] == 0 ? CRTC.crtR12GrXPort[0] : CRTC.crtR12GrXTest[0];
  2416:            if (CRTC.crtR12GrXCurr[0] != curr) {
  2417:              CRTC.crtR12GrXCurr[0] = curr;
  2418:              CRTC.crtAllStamp += 2;
  2419:            }
  2420:          }
  2421:          return;
  2422:        case CRTC.CRT_R13_GR_Y_0:  //R13
  2423:          CRTC.crtR13GrYPort[0] = d & 1023;
  2424:          {
  2425:            int curr = CRTC.crtR13GrYMask[0] == 0 ? CRTC.crtR13GrYPort[0] : CRTC.crtR13GrYTest[0];
  2426:            if (CRTC.crtR13GrYCurr[0] != curr) {
  2427:              CRTC.crtR13GrYCurr[0] = curr;
  2428:              CRTC.crtAllStamp += 2;
  2429:            }
  2430:          }
  2431:          return;
  2432:        case CRTC.CRT_R14_GR_X_1:  //R14
  2433:          CRTC.crtR12GrXPort[1] = d & 511;
  2434:          {
  2435:            int curr = CRTC.crtR12GrXMask[1] == 0 ? CRTC.crtR12GrXPort[1] : CRTC.crtR12GrXTest[1];
  2436:            if (CRTC.crtR12GrXCurr[1] != curr) {
  2437:              CRTC.crtR12GrXCurr[1] = curr;
  2438:              CRTC.crtAllStamp += 2;
  2439:            }
  2440:          }
  2441:          return;
  2442:        case CRTC.CRT_R15_GR_Y_1:  //R15
  2443:          CRTC.crtR13GrYPort[1] = d & 511;
  2444:          {
  2445:            int curr = CRTC.crtR13GrYMask[1] == 0 ? CRTC.crtR13GrYPort[1] : CRTC.crtR13GrYTest[1];
  2446:            if (CRTC.crtR13GrYCurr[1] != curr) {
  2447:              CRTC.crtR13GrYCurr[1] = curr;
  2448:              CRTC.crtAllStamp += 2;
  2449:            }
  2450:          }
  2451:          return;
  2452:        case CRTC.CRT_R16_GR_X_2:  //R16
  2453:          CRTC.crtR12GrXPort[2] = d & 511;
  2454:          {
  2455:            int curr = CRTC.crtR12GrXMask[2] == 0 ? CRTC.crtR12GrXPort[2] : CRTC.crtR12GrXTest[2];
  2456:            if (CRTC.crtR12GrXCurr[2] != curr) {
  2457:              CRTC.crtR12GrXCurr[2] = curr;
  2458:              CRTC.crtAllStamp += 2;
  2459:            }
  2460:          }
  2461:          return;
  2462:        case CRTC.CRT_R17_GR_Y_2:  //R17
  2463:          CRTC.crtR13GrYPort[2] = d & 511;
  2464:          {
  2465:            int curr = CRTC.crtR13GrYMask[2] == 0 ? CRTC.crtR13GrYPort[2] : CRTC.crtR13GrYTest[2];
  2466:            if (CRTC.crtR13GrYCurr[2] != curr) {
  2467:              CRTC.crtR13GrYCurr[2] = curr;
  2468:              CRTC.crtAllStamp += 2;
  2469:            }
  2470:          }
  2471:          return;
  2472:        case CRTC.CRT_R18_GR_X_3:  //R18
  2473:          CRTC.crtR12GrXPort[3] = d & 511;
  2474:          {
  2475:            int curr = CRTC.crtR12GrXMask[3] == 0 ? CRTC.crtR12GrXPort[3] : CRTC.crtR12GrXTest[3];
  2476:            if (CRTC.crtR12GrXCurr[3] != curr) {
  2477:              CRTC.crtR12GrXCurr[3] = curr;
  2478:              CRTC.crtAllStamp += 2;
  2479:            }
  2480:          }
  2481:          return;
  2482:        case CRTC.CRT_R19_GR_Y_3:  //R19
  2483:          CRTC.crtR13GrYPort[3] = d & 511;
  2484:          {
  2485:            int curr = CRTC.crtR13GrYMask[3] == 0 ? CRTC.crtR13GrYPort[3] : CRTC.crtR13GrYTest[3];
  2486:            if (CRTC.crtR13GrYCurr[3] != curr) {
  2487:              CRTC.crtR13GrYCurr[3] = curr;
  2488:              CRTC.crtAllStamp += 2;
  2489:            }
  2490:          }
  2491:          return;
  2492:        case CRTC.CRT_R20_MODE:  //R20
  2493:          CRTC.crtSetMemoryMode (d >> 8);
  2494:          CRTC.crtHighResoPort = d >>> 4 & 1;
  2495:          CRTC.crtVResoPort    = d >>> 2 & 3;
  2496:          CRTC.crtHResoPort    = d       & 3;
  2497:          int highResoCurr = CRTC.crtHighResoMask == 0 ? CRTC.crtHighResoPort : CRTC.crtHighResoTest;
  2498:          int vResoCurr = CRTC.crtVResoMask == 0 ? CRTC.crtVResoPort : CRTC.crtVResoTest;
  2499:          int hResoCurr = CRTC.crtHResoMask == 0 ? CRTC.crtHResoPort : CRTC.crtHResoTest;
  2500:          if (CRTC.crtHighResoCurr != highResoCurr ||
  2501:              CRTC.crtVResoCurr != vResoCurr ||
  2502:              CRTC.crtHResoCurr != hResoCurr) {
  2503:            CRTC.crtHighResoCurr = highResoCurr;
  2504:            CRTC.crtVResoCurr = vResoCurr;
  2505:            CRTC.crtHResoCurr = hResoCurr;
  2506:            CRTC.crtRestart ();
  2507:          }
  2508:          return;
  2509:        case CRTC.CRT_R21_SELECT:  //R21
  2510:          CRTC.crtBitMask   = d << 22 < 0;  //(d & 512) != 0
  2511:          CRTC.crtSimAccess = d << 23 < 0;  //(d & 256) != 0
  2512:          CRTC.crtSimPlane3 = (byte) d < 0;  //(d & 128) != 0。d << 24 < 0
  2513:          CRTC.crtSimPlane2 = d << 25 < 0;  //(d & 64) != 0
  2514:          CRTC.crtSimPlane1 = d << 26 < 0;  //(d & 32) != 0
  2515:          CRTC.crtSimPlane0 = d << 27 < 0;  //(d & 16) != 0
  2516:          CRTC.crtCCPlane3  = XEiJ.TEST_BIT_3_SHIFT ? d << 31 - 3 < 0 : (d & 8) != 0;
  2517:          CRTC.crtCCPlane2  = XEiJ.TEST_BIT_2_SHIFT ? d << 31 - 2 < 0 : (d & 4) != 0;
  2518:          CRTC.crtCCPlane1  = XEiJ.TEST_BIT_1_SHIFT ? d << 31 - 1 < 0 : (d & 2) != 0;
  2519:          CRTC.crtCCPlane0  = XEiJ.TEST_BIT_0_SHIFT ? d << 31 - 0 < 0 : (d & 1) != 0;
  2520:          return;
  2521:        case CRTC.CRT_R22_BLOCK:  //R22
  2522:          CRTC.crtR22SrcBlock = d >> 8 & 255;
  2523:          CRTC.crtR22DstBlock = d      & 255;
  2524:          return;
  2525:        case CRTC.CRT_R23_MASK:  //R23
  2526:          CRTC.crtR23Mask = (char) d;
  2527:          return;
  2528:        case CRTC.CRT_R24:  //R24
  2529:          return;
  2530:        case CRTC.CRT_ACTION :  //動作ポート
  2531:          {
  2532:            boolean rasterCopyOn = (d & 8) != 0;
  2533:            if (CRTC.crtRasterCopyOn != rasterCopyOn) {
  2534:              CRTC.crtRasterCopyOn = rasterCopyOn;  //ラスタコピー
  2535:              if (CRTC.CRT_RASTER_HASH_ON) {
  2536:                CRTC.crtUpdateRasterHash ();
  2537:              }
  2538:            }
  2539:          }
  2540:          CRTC.crtClearStandby = (d & 2) != 0;  //高速クリア
  2541:          return;
  2542:        }
  2543:        super.mmdWw (a, d);  //バスエラー
  2544:      }
  2545:     @Override protected void mmdWl (int a, int d) throws M68kException {
  2546:        a &= XEiJ.BUS_MOTHER_MASK;
  2547:        mmdWw (a    , d >> 16);
  2548:        mmdWw (a + 2, d      );
  2549:      }
  2550:   },  //MMD_CRT
  2551: 
  2552:   //--------------------------------------------------------------------------------
  2553:   //MMD_VCN ビデオコントローラ
  2554:   MMD_VCN {
  2555:     @Override public String toString () {
  2556:       return Multilingual.mlnJapanese ? "ビデオコントローラ" : "Video Controller";
  2557:     }
  2558:     //リード
  2559:     @Override protected int mmdRbz (int a) throws M68kException {
  2560:        a &= XEiJ.BUS_MOTHER_MASK;
  2561:        int ah = a & ~0xff;
  2562:        int al = a & 0x01;
  2563:        return (ah < 0x00e82200 ? al == 0 ? VideoController.vcnPal16G8[a >> 1 & 255] >> 8 : VideoController.vcnPal16G8[a >> 1 & 255] & 255 :  //グラフィックスパレット
  2564:                ah < 0x00e82400 ? al == 0 ? VideoController.vcnPal16TS[a >> 1 & 255] >> 8 : VideoController.vcnPal16TS[a >> 1 & 255] & 255 :  //テキストスプライトパレット
  2565:                ah == VideoController.VCN_REG1 ? al == 0 ? VideoController.vcnReg1Port >> 8 : VideoController.vcnReg1Port & 255 :
  2566:                ah == VideoController.VCN_REG2 ? al == 0 ? VideoController.vcnReg2Port >> 8 : VideoController.vcnReg2Port & 255 :
  2567:                ah == VideoController.VCN_REG3 ? al == 0 ? VideoController.vcnReg3Port >> 8 : VideoController.vcnReg3Port & 255 : 0);
  2568:      }
  2569:     @Override protected int mmdRwz (int a) throws M68kException {
  2570:        a &= XEiJ.BUS_MOTHER_MASK;
  2571:        int ah = a & ~0xff;
  2572:        return (ah < 0x00e82200 ? VideoController.vcnPal16G8[a >> 1 & 255] :  //グラフィックスパレット
  2573:                ah < 0x00e82400 ? VideoController.vcnPal16TS[a >> 1 & 255] :  //テキストスプライトパレット
  2574:                ah == VideoController.VCN_REG1 ? VideoController.vcnReg1Port :
  2575:                ah == VideoController.VCN_REG2 ? VideoController.vcnReg2Port :
  2576:                ah == VideoController.VCN_REG3 ? VideoController.vcnReg3Port : 0);
  2577:      }
  2578:     @Override protected int mmdRls (int a) throws M68kException {
  2579:        a &= XEiJ.BUS_MOTHER_MASK;
  2580:        return mmdRwz (a) << 16 | mmdRwz (a + 2);
  2581:      }
  2582:     //ライト
  2583:     @Override protected void mmdWb (int a, int d) throws M68kException {
  2584:        a &= XEiJ.BUS_MOTHER_MASK;
  2585:        int ah = a & ~0xff;
  2586:        int al = a & 0x01;
  2587:        if (ah < 0x00e82200) {  //グラフィックスパレット
  2588:          d &= 0xff;
  2589:          int n = a >> 1 & 255;
  2590:          if (al == 0) {
  2591:            VideoController.vcnPal32G8[n] = VideoController.vcnPalTbl[VideoController.vcnPal16G8[n] = d << 8 | 0xff & VideoController.vcnPal16G8[n]];
  2592:            if ((n & 1) == 0) {
  2593:              VideoController.vcnPal8G16L[n] = d;
  2594:            } else {
  2595:              VideoController.vcnPal8G16H[n - 1] = d << 8;
  2596:            }
  2597:          } else {
  2598:            VideoController.vcnPal32G8[n] = VideoController.vcnPalTbl[VideoController.vcnPal16G8[n] = 0xff00 & VideoController.vcnPal16G8[n] | d];
  2599:            if ((n & 1) == 0) {
  2600:              VideoController.vcnPal8G16L[n + 1] = d;
  2601:            } else {
  2602:              VideoController.vcnPal8G16H[n] = d << 8;
  2603:            }
  2604:          }
  2605:          if ((0x001f & VideoController.vcnReg3Curr) != 0) {  //グラフィックス画面が表示されている
  2606:            CRTC.crtAllStamp += 2;
  2607:          }
  2608:        } else if (ah < 0x00e82400) {  //テキストスプライトパレット
  2609:          d &= 0xff;
  2610:          int n = a >> 1 & 255;
  2611:          VideoController.vcnPal16TS[n] = d = al == 0 ? d << 8 | 0xff & VideoController.vcnPal16TS[n] : 0xff00 & VideoController.vcnPal16TS[n] | d;
  2612:          VideoController.vcnPal32TS[n] = VideoController.vcnPalTbl[d];
  2613:          if (VideoController.vcnReg3Curr << 31 - 6 < 0 &&  //スプライト画面が表示されている
  2614:              SpriteScreen.sprReg4BgCtrlCurr << 31 - 9 < 0 ||  //スプライト画面が表示されている
  2615:              VideoController.vcnReg3Curr << 31 - 5 < 0 &&  //テキスト画面が表示されている
  2616:              n < 16) {  //テキストパレット
  2617:            CRTC.crtAllStamp += 2;
  2618:          }
  2619:        } else if (ah == VideoController.VCN_REG1) {
  2620:          d = al == 0 ? 0x00 : 0x07 & d;
  2621:          if (VideoController.vcnReg1Port != d) {
  2622:            VideoController.vcnReg1Port = d;
  2623:            VideoController.vcnReg1Curr = VideoController.vcnReg1Port & ~VideoController.vcnReg1Mask | VideoController.vcnReg1Test & VideoController.vcnReg1Mask;
  2624:            VideoController.vcnUpdateMode ();
  2625:          }
  2626:        } else if (ah == VideoController.VCN_REG2) {
  2627:          d = al == 0 ? (0x3f & d) << 8 | 0xff & VideoController.vcnReg2Port : 0xff00 & VideoController.vcnReg2Port | 0xff & d;
  2628:          if (VideoController.vcnReg2Port != d) {
  2629:            VideoController.vcnReg2Port = d;
  2630:            VideoController.vcnReg2Curr = VideoController.vcnReg2Port & ~VideoController.vcnReg2Mask | VideoController.vcnReg2Test & VideoController.vcnReg2Mask;
  2631:            VideoController.vcnUpdateMode ();
  2632:          }
  2633:        } else if (ah == VideoController.VCN_REG3) {
  2634:          d = al == 0 ? (0xff & d) << 8 | 0xff & VideoController.vcnReg3Port : 0xff00 & VideoController.vcnReg3Port | 0xff & d;
  2635:          if (VideoController.vcnReg3Port != d) {
  2636:            VideoController.vcnReg3Port = d;
  2637:            VideoController.vcnReg3Curr = VideoController.vcnReg3Port & ~VideoController.vcnReg3Mask | VideoController.vcnReg3Test & VideoController.vcnReg3Mask;
  2638:            VideoController.vcnUpdateMode ();
  2639:          }
  2640:        }
  2641:      }
  2642:     @Override protected void mmdWw (int a, int d) throws M68kException {
  2643:        a &= XEiJ.BUS_MOTHER_MASK;
  2644:        int ah = a & ~0xff;
  2645:        if (ah < 0x00e82200) {  //グラフィックスパレット
  2646:          int n = a >> 1 & 255;
  2647:          VideoController.vcnPal32G8[n] = VideoController.vcnPalTbl[VideoController.vcnPal16G8[n] = (char) d];
  2648:          if ((n & 1) == 0) {
  2649:            VideoController.vcnPal8G16L[n] = 0xff & d >> 8;
  2650:            VideoController.vcnPal8G16L[n + 1] = 0xff & d;
  2651:          } else {
  2652:            VideoController.vcnPal8G16H[n - 1] = 0xff00 & d;
  2653:            VideoController.vcnPal8G16H[n] = 0xff00 & d << 8;
  2654:          }
  2655:          if ((0x001f & VideoController.vcnReg3Curr) != 0) {  //グラフィックス画面が表示されている
  2656:            CRTC.crtAllStamp += 2;
  2657:          }
  2658:        } else if (ah < 0x00e82400) {  //テキストスプライトパレット
  2659:          int n = a >> 1 & 255;
  2660:          VideoController.vcnPal16TS[n] = d = (char) d;
  2661:          VideoController.vcnPal32TS[n] = VideoController.vcnPalTbl[d];
  2662:          if (VideoController.vcnReg3Curr << 31 - 6 < 0 &&  //スプライト画面が表示されている
  2663:              SpriteScreen.sprReg4BgCtrlCurr << 31 - 9 < 0 ||  //スプライト画面が表示されている
  2664:              VideoController.vcnReg3Curr << 31 - 5 < 0 &&  //テキスト画面が表示されている
  2665:              n < 16) {  //テキストパレット
  2666:            CRTC.crtAllStamp += 2;
  2667:          }
  2668:        } else if (ah == VideoController.VCN_REG1) {
  2669:          d &= 0x0007;
  2670:          if (VideoController.vcnReg1Port != d) {
  2671:            VideoController.vcnReg1Port = d;
  2672:            VideoController.vcnReg1Curr = VideoController.vcnReg1Port & ~VideoController.vcnReg1Mask | VideoController.vcnReg1Test & VideoController.vcnReg1Mask;
  2673:            VideoController.vcnUpdateMode ();
  2674:          }
  2675:        } else if (ah == VideoController.VCN_REG2) {
  2676:          d &= 0x3fff;
  2677:          if (VideoController.vcnReg2Port != d) {
  2678:            VideoController.vcnReg2Port = d;
  2679:            VideoController.vcnReg2Curr = VideoController.vcnReg2Port & ~VideoController.vcnReg2Mask | VideoController.vcnReg2Test & VideoController.vcnReg2Mask;
  2680:            VideoController.vcnUpdateMode ();
  2681:          }
  2682:        } else if (ah == VideoController.VCN_REG3) {
  2683:          d &= 0xffff;
  2684:          if (VideoController.vcnReg3Port != d) {
  2685:            VideoController.vcnReg3Port = d;
  2686:            VideoController.vcnReg3Curr = VideoController.vcnReg3Port & ~VideoController.vcnReg3Mask | VideoController.vcnReg3Test & VideoController.vcnReg3Mask;
  2687:            VideoController.vcnUpdateMode ();
  2688:          }
  2689:        }
  2690:      }
  2691:     @Override protected void mmdWl (int a, int d) throws M68kException {
  2692:        a &= XEiJ.BUS_MOTHER_MASK;
  2693:        mmdWw (a    , d >> 16);
  2694:        mmdWw (a + 2, d      );
  2695:      }
  2696:   },  //MMD_VCN
  2697: 
  2698:   //--------------------------------------------------------------------------------
  2699:   //MMD_DMA DMAコントローラ
  2700:   MMD_DMA {
  2701:     @Override public String toString () {
  2702:       return Multilingual.mlnJapanese ? "DMA コントローラ" : "DMA Controller";
  2703:     }
  2704:     //リード
  2705:     @Override protected int mmdRbz (int a) throws M68kException {
  2706:        a &= XEiJ.BUS_MOTHER_MASK;
  2707:        int d;
  2708:        int al = a & 255;
  2709:        if (al == HD63450.DMA_GCR) {
  2710:          d = HD63450.dmaBT | HD63450.dmaBR;
  2711:          if (HD63450.DMA_DEBUG_TRACE != 0) {
  2712:            System.out.printf ("%d %08x HD63450.dmaRbz(0x%08x)=0x%02x\n", XEiJ.mpuClockTime, XEiJ.regPC0, a, d);
  2713:          }
  2714:        } else {
  2715:          int i = al >> 6;  //チャンネル
  2716:          switch (al & 0x3f) {
  2717:          case HD63450.DMA_CSR:
  2718:            d = HD63450.dmaCOC[i] | HD63450.dmaBLC[i] | HD63450.dmaNDT[i] | HD63450.dmaERR[i] | HD63450.dmaACT[i] | HD63450.dmaDIT[i] | HD63450.dmaPCT[i] | HD63450.dmaPCS[i];
  2719:            break;
  2720:          case HD63450.DMA_CER:
  2721:            d = HD63450.dmaErrorCode[i];
  2722:            break;
  2723:          case HD63450.DMA_DCR:
  2724:            d = HD63450.dmaXRM[i] | HD63450.dmaDTYP[i] | HD63450.dmaDPS[i] | HD63450.dmaPCL[i];
  2725:            break;
  2726:          case HD63450.DMA_OCR:
  2727:            d = HD63450.dmaDIR[i] | HD63450.dmaBTD[i] | HD63450.dmaSIZE[i] | HD63450.dmaCHAIN[i] | HD63450.dmaREQG[i];
  2728:            break;
  2729:          case HD63450.DMA_SCR:
  2730:            d = HD63450.dmaMAC[i] | HD63450.dmaDAC[i];
  2731:            break;
  2732:          case HD63450.DMA_CCR:
  2733:            d = HD63450.dmaSTR[i] | HD63450.dmaCNT[i] | HD63450.dmaHLT[i] | HD63450.dmaSAB[i] | HD63450.dmaITE[i];
  2734:            break;
  2735:          case HD63450.DMA_MTC:
  2736:            d = HD63450.dmaMTC[i] >> 8;
  2737:            break;
  2738:          case HD63450.DMA_MTC + 1:
  2739:            d = HD63450.dmaMTC[i] & 255;
  2740:            break;
  2741:          case HD63450.DMA_MAR:
  2742:            d = HD63450.dmaMAR[i] >>> 24;
  2743:            break;
  2744:          case HD63450.DMA_MAR + 1:
  2745:            d = HD63450.dmaMAR[i] >> 16 & 255;
  2746:            break;
  2747:          case HD63450.DMA_MAR + 2:
  2748:            d = (char) HD63450.dmaMAR[i] >> 8;
  2749:            break;
  2750:          case HD63450.DMA_MAR + 3:
  2751:            d = HD63450.dmaMAR[i] & 255;
  2752:            break;
  2753:          case HD63450.DMA_DAR:
  2754:            d = HD63450.dmaDAR[i] >>> 24;
  2755:            break;
  2756:          case HD63450.DMA_DAR + 1:
  2757:            d = HD63450.dmaDAR[i] >> 16 & 255;
  2758:            break;
  2759:          case HD63450.DMA_DAR + 2:
  2760:            d = (char) HD63450.dmaDAR[i] >> 8;
  2761:            break;
  2762:          case HD63450.DMA_DAR + 3:
  2763:            d = HD63450.dmaDAR[i] & 255;
  2764:            break;
  2765:          case HD63450.DMA_BTC:
  2766:            d = HD63450.dmaBTC[i] >> 8;
  2767:            break;
  2768:          case HD63450.DMA_BTC + 1:
  2769:            d = HD63450.dmaBTC[i] & 255;
  2770:            break;
  2771:          case HD63450.DMA_BAR:
  2772:            d = HD63450.dmaBAR[i] >>> 24;
  2773:            break;
  2774:          case HD63450.DMA_BAR + 1:
  2775:            d = HD63450.dmaBAR[i] >> 16 & 255;
  2776:            break;
  2777:          case HD63450.DMA_BAR + 2:
  2778:            d = (char) HD63450.dmaBAR[i] >> 8;
  2779:            break;
  2780:          case HD63450.DMA_BAR + 3:
  2781:            d = HD63450.dmaBAR[i] & 255;
  2782:            break;
  2783:          case HD63450.DMA_NIV:
  2784:            d = HD63450.dmaNIV[i];
  2785:            break;
  2786:          case HD63450.DMA_EIV:
  2787:            d = HD63450.dmaEIV[i];
  2788:            break;
  2789:          case HD63450.DMA_MFC:
  2790:            d = HD63450.dmaMFC[i];
  2791:            break;
  2792:          case HD63450.DMA_CPR:
  2793:            d = HD63450.dmaCP[i];
  2794:            break;
  2795:          case HD63450.DMA_DFC:
  2796:            d = HD63450.dmaDFC[i];
  2797:            break;
  2798:          case HD63450.DMA_BFC:
  2799:            d = HD63450.dmaBFC[i];
  2800:            break;
  2801:          default:
  2802:            d = 0;
  2803:          }
  2804:          if (HD63450.DMA_DEBUG_TRACE != 0 && (HD63450.DMA_DEBUG_TRACE & 1 << i) != 0) {
  2805:            System.out.printf ("%d %08x HD63450.dmaRbz(0x%08x)=0x%02x\n", XEiJ.mpuClockTime, XEiJ.regPC0, a, d);
  2806:          }
  2807:        }
  2808:        return d;
  2809:      }
  2810:     @Override protected int mmdRwz (int a) throws M68kException {
  2811:        a &= XEiJ.BUS_MOTHER_MASK;
  2812:        int d;
  2813:        int al = a & 255;
  2814:        int i = al >> 6;  //チャンネル
  2815:        switch (al & 0x3f) {
  2816:        case HD63450.DMA_MTC:
  2817:          d = HD63450.dmaMTC[i];
  2818:          break;
  2819:        case HD63450.DMA_MAR:
  2820:          d = HD63450.dmaMAR[i] >>> 16;
  2821:          break;
  2822:        case HD63450.DMA_MAR + 2:
  2823:          d = (char) HD63450.dmaMAR[i];
  2824:          break;
  2825:        case HD63450.DMA_DAR:
  2826:          d = HD63450.dmaDAR[i] >>> 16;
  2827:          break;
  2828:        case HD63450.DMA_DAR + 2:
  2829:          d = (char) HD63450.dmaDAR[i];
  2830:          break;
  2831:        case HD63450.DMA_BTC:
  2832:          d = HD63450.dmaBTC[i];
  2833:          break;
  2834:        case HD63450.DMA_BAR:
  2835:          d = HD63450.dmaBAR[i] >>> 16;
  2836:          break;
  2837:        case HD63450.DMA_BAR + 2:
  2838:          d = (char) HD63450.dmaBAR[i];
  2839:          break;
  2840:        default:
  2841:          d = mmdRbz (a) << 8 | mmdRbz (a + 1);
  2842:        }
  2843:        if (HD63450.DMA_DEBUG_TRACE != 0 && (HD63450.DMA_DEBUG_TRACE & 1 << i) != 0) {
  2844:          System.out.printf ("%d %08x HD63450.dmaRwz(0x%08x)=0x%04x\n", XEiJ.mpuClockTime, XEiJ.regPC0, a, d);
  2845:        }
  2846:        return d;
  2847:      }
  2848:     @Override protected int mmdRls (int a) throws M68kException {
  2849:        a &= XEiJ.BUS_MOTHER_MASK;
  2850:        int d;
  2851:        int al = a & 255;
  2852:        int i = al >> 6;  //チャンネル
  2853:        switch (al & 0x3f) {
  2854:        case HD63450.DMA_MAR:
  2855:          d = HD63450.dmaMAR[i];
  2856:          break;
  2857:        case HD63450.DMA_DAR:
  2858:          d = HD63450.dmaDAR[i];
  2859:          break;
  2860:        case HD63450.DMA_BAR:
  2861:          d = HD63450.dmaBAR[i];
  2862:          break;
  2863:        default:
  2864:          d = mmdRwz (a) << 16 | mmdRwz (a + 2);
  2865:        }
  2866:        if (HD63450.DMA_DEBUG_TRACE != 0 && (HD63450.DMA_DEBUG_TRACE & 1 << i) != 0) {
  2867:          System.out.printf ("%d %08x HD63450.dmaRls(0x%08x)=0x%08x\n", XEiJ.mpuClockTime, XEiJ.regPC0, a, d);
  2868:        }
  2869:        return d;
  2870:      }
  2871:     //ライト
  2872:     @Override protected void mmdWb (int a, int d) throws M68kException {
  2873:        a &= XEiJ.BUS_MOTHER_MASK;
  2874:        int al = a & 255;
  2875:        if (al == HD63450.DMA_GCR) {
  2876:          if (HD63450.DMA_DEBUG_TRACE != 0) {
  2877:            System.out.printf ("%d %08x HD63450.dmaWb(0x%08x,0x%02x)\n", XEiJ.mpuClockTime, XEiJ.regPC0, a, d);
  2878:          }
  2879:          HD63450.dmaBT = d & HD63450.DMA_BT;
  2880:          HD63450.dmaBR = d & HD63450.DMA_BR;
  2881:          HD63450.dmaBurstInterval = HD63450.DMA_CLOCK_UNIT << 4 + (HD63450.dmaBT >> 2);
  2882:          HD63450.dmaBurstSpan = HD63450.dmaBurstInterval >> 1 + (HD63450.dmaBR & 3);
  2883:          return;
  2884:        }
  2885:        int i = al >> 6;  //チャンネル
  2886:        if (HD63450.DMA_DEBUG_TRACE != 0 && (HD63450.DMA_DEBUG_TRACE & 1 << i) != 0) {
  2887:          System.out.printf ("%d %08x HD63450.dmaWb(0x%08x,0x%02x)\n", XEiJ.mpuClockTime, XEiJ.regPC0, a, d);
  2888:        }
  2889:        switch (al & 0x3f) {
  2890:        case HD63450.DMA_CSR:
  2891:          if ((byte) d == -1) {  //HD63450.DMA_CSRは-1を書き込むとクリアされる。それ以外は無視
  2892:            HD63450.dmaCOC[i] = 0;
  2893:            HD63450.dmaBLC[i] = 0;
  2894:            HD63450.dmaNDT[i] = 0;
  2895:            HD63450.dmaERR[i] = 0;
  2896:          }
  2897:          return;
  2898:        case HD63450.DMA_CER:
  2899:          //HD63450.DMA_CERはread-only
  2900:          return;
  2901:        case HD63450.DMA_DCR:
  2902:          if (HD63450.dmaACT[i] != 0) {
  2903:            HD63450.dmaErrorExit (i, HD63450.DMA_TIMING_ERROR);
  2904:            return;
  2905:          }
  2906:          HD63450.dmaXRM[i] = d & HD63450.DMA_XRM;
  2907:          HD63450.dmaDTYP[i] = d & HD63450.DMA_DTYP;
  2908:          HD63450.dmaDPS[i] = d & HD63450.DMA_DPS;
  2909:          HD63450.dmaPCL[i] = d & HD63450.DMA_PCL;
  2910:          return;
  2911:        case HD63450.DMA_OCR:
  2912:          HD63450.dmaDIR[i] = d & HD63450.DMA_DIR;
  2913:          HD63450.dmaBTD[i] = d & HD63450.DMA_BTD;
  2914:          HD63450.dmaSIZE[i] = d & HD63450.DMA_SIZE;
  2915:          HD63450.dmaCHAIN[i] = d & HD63450.DMA_CHAIN;
  2916:          HD63450.dmaREQG[i] = d & HD63450.DMA_REQG;
  2917:          return;
  2918:        case HD63450.DMA_SCR:
  2919:          if (HD63450.dmaACT[i] != 0) {
  2920:            HD63450.dmaErrorExit (i, HD63450.DMA_TIMING_ERROR);
  2921:            return;
  2922:          }
  2923:          HD63450.dmaMAC[i] = d & HD63450.DMA_MAC;
  2924:          HD63450.dmaMACValue[i] = HD63450.dmaMAC[i] == HD63450.DMA_INC_MAR ? 1 : HD63450.dmaMAC[i] == HD63450.DMA_DEC_MAR ? -1 : 0;
  2925:          HD63450.dmaDAC[i] = d & HD63450.DMA_DAC;
  2926:          HD63450.dmaDACValue[i] = HD63450.dmaDAC[i] == HD63450.DMA_INC_DAR ? 1 : HD63450.dmaDAC[i] == HD63450.DMA_DEC_DAR ? -1 : 0;
  2927:          return;
  2928:        case HD63450.DMA_CCR:
  2929:          HD63450.dmaHLT[i] = d & HD63450.DMA_HLT;
  2930:          HD63450.dmaITE[i] = d & HD63450.DMA_ITE;
  2931:          //HD63450.DMA_CNT
  2932:          if ((d & HD63450.DMA_CNT) != 0) {
  2933:            if ((HD63450.dmaACT[i] == 0 && (d & HD63450.DMA_STR) == 0) || HD63450.dmaBLC[i] != 0) {  //動作中でないかブロック転送完了済みの状態でHD63450.DMA_CNTをセットしようとした
  2934:              HD63450.dmaErrorExit (i, HD63450.DMA_TIMING_ERROR);
  2935:              return;
  2936:            }
  2937:            if (HD63450.dmaCHAIN[i] != HD63450.DMA_NO_CHAINING) {  //チェインモードのときHD63450.DMA_CNTをセットしようとした
  2938:              HD63450.dmaErrorExit (i, HD63450.DMA_CONFIGURATION_ERROR);
  2939:              return;
  2940:            }
  2941:            HD63450.dmaCNT[i] = HD63450.DMA_CNT;  //HD63450.DMA_CNTに0を書き込んでもクリアされない
  2942:          }
  2943:          //HD63450.DMA_SAB
  2944:          if ((d & HD63450.DMA_SAB) != 0) {
  2945:            //HD63450.dmaSABには書き込まない。SABは読み出すと常に0
  2946:            HD63450.dmaCOC[i] = 0;
  2947:            HD63450.dmaBLC[i] = 0;
  2948:            HD63450.dmaNDT[i] = 0;
  2949:            HD63450.dmaHLT[i] = 0;
  2950:            HD63450.dmaCNT[i] = 0;
  2951:            if (HD63450.dmaACT[i] != 0 || (d & HD63450.DMA_STR) != 0) {  //動作中
  2952:              HD63450.dmaErrorExit (i, HD63450.DMA_SOFTWARE_ABORT);
  2953:            }
  2954:            return;
  2955:          }
  2956:          //HD63450.DMA_STR
  2957:          if ((d & HD63450.DMA_STR) != 0) {
  2958:            HD63450.dmaStart (i);
  2959:          }
  2960:          return;
  2961:        case HD63450.DMA_MTC:
  2962:          if (HD63450.dmaACT[i] != 0) {
  2963:            HD63450.dmaErrorExit (i, HD63450.DMA_TIMING_ERROR);
  2964:            return;
  2965:          }
  2966:          HD63450.dmaMTC[i] = (0xff & d) << 8 | 0xff & HD63450.dmaMTC[i];
  2967:          return;
  2968:        case HD63450.DMA_MTC + 1:
  2969:          if (HD63450.dmaACT[i] != 0) {
  2970:            HD63450.dmaErrorExit (i, HD63450.DMA_TIMING_ERROR);
  2971:            return;
  2972:          }
  2973:          HD63450.dmaMTC[i] = 0xff00 & HD63450.dmaMTC[i] | 0xff & d;
  2974:          return;
  2975:        case HD63450.DMA_MAR:
  2976:          if (HD63450.dmaACT[i] != 0) {
  2977:            HD63450.dmaErrorExit (i, HD63450.DMA_TIMING_ERROR);
  2978:            return;
  2979:          }
  2980:          HD63450.dmaMAR[i] = d << 24 | 0xffffff & HD63450.dmaMAR[i];
  2981:          return;
  2982:        case HD63450.DMA_MAR + 1:
  2983:          if (HD63450.dmaACT[i] != 0) {
  2984:            HD63450.dmaErrorExit (i, HD63450.DMA_TIMING_ERROR);
  2985:            return;
  2986:          }
  2987:          HD63450.dmaMAR[i] = (0xff & d) << 16 | 0xff00ffff & HD63450.dmaMAR[i];
  2988:          return;
  2989:        case HD63450.DMA_MAR + 2:
  2990:          if (HD63450.dmaACT[i] != 0) {
  2991:            HD63450.dmaErrorExit (i, HD63450.DMA_TIMING_ERROR);
  2992:            return;
  2993:          }
  2994:          HD63450.dmaMAR[i] = (0xff & d) << 8 | 0xffff00ff & HD63450.dmaMAR[i];
  2995:          return;
  2996:        case HD63450.DMA_MAR + 3:
  2997:          if (HD63450.dmaACT[i] != 0) {
  2998:            HD63450.dmaErrorExit (i, HD63450.DMA_TIMING_ERROR);
  2999:            return;
  3000:          }
  3001:          HD63450.dmaMAR[i] = ~0xff & HD63450.dmaMAR[i] | 0xff & d;
  3002:          return;
  3003:        case HD63450.DMA_DAR:
  3004:          if (HD63450.dmaACT[i] != 0) {
  3005:            HD63450.dmaErrorExit (i, HD63450.DMA_TIMING_ERROR);
  3006:            return;
  3007:          }
  3008:          HD63450.dmaDAR[i] = d << 24 | 0xffffff & HD63450.dmaDAR[i];
  3009:          return;
  3010:        case HD63450.DMA_DAR + 1:
  3011:          if (HD63450.dmaACT[i] != 0) {
  3012:            HD63450.dmaErrorExit (i, HD63450.DMA_TIMING_ERROR);
  3013:            return;
  3014:          }
  3015:          HD63450.dmaDAR[i] = (0xff & d) << 16 | 0xff00ffff & HD63450.dmaDAR[i];
  3016:          return;
  3017:        case HD63450.DMA_DAR + 2:
  3018:          if (HD63450.dmaACT[i] != 0) {
  3019:            HD63450.dmaErrorExit (i, HD63450.DMA_TIMING_ERROR);
  3020:            return;
  3021:          }
  3022:          HD63450.dmaDAR[i] = (0xff & d) << 8 | 0xffff00ff & HD63450.dmaDAR[i];
  3023:          return;
  3024:        case HD63450.DMA_DAR + 3:
  3025:          if (HD63450.dmaACT[i] != 0) {
  3026:            HD63450.dmaErrorExit (i, HD63450.DMA_TIMING_ERROR);
  3027:            return;
  3028:          }
  3029:          HD63450.dmaDAR[i] = ~0xff & HD63450.dmaDAR[i] | 0xff & d;
  3030:          return;
  3031:        case HD63450.DMA_BTC:
  3032:          HD63450.dmaBTC[i] = (0xff & d) << 8 | 0xff & HD63450.dmaBTC[i];
  3033:          return;
  3034:        case HD63450.DMA_BTC + 1:
  3035:          HD63450.dmaBTC[i] = 0xff00 & HD63450.dmaBTC[i] | 0xff & d;
  3036:          return;
  3037:        case HD63450.DMA_BAR:
  3038:          HD63450.dmaBAR[i] = d << 24 | 0xffffff & HD63450.dmaBAR[i];
  3039:          return;
  3040:        case HD63450.DMA_BAR + 1:
  3041:          HD63450.dmaBAR[i] = (0xff & d) << 16 | 0xff00ffff & HD63450.dmaBAR[i];
  3042:          return;
  3043:        case HD63450.DMA_BAR + 2:
  3044:          HD63450.dmaBAR[i] = (0xff & d) << 8 | 0xffff00ff & HD63450.dmaBAR[i];
  3045:          return;
  3046:        case HD63450.DMA_BAR + 3:
  3047:          HD63450.dmaBAR[i] = ~0xff & HD63450.dmaBAR[i] | 0xff & d;
  3048:          return;
  3049:        case HD63450.DMA_NIV:
  3050:          HD63450.dmaNIV[i] = 0xff & d;
  3051:          return;
  3052:        case HD63450.DMA_EIV:
  3053:          HD63450.dmaEIV[i] = 0xff & d;
  3054:          return;
  3055:        case HD63450.DMA_MFC:
  3056:          if (HD63450.dmaACT[i] != 0) {
  3057:            HD63450.dmaErrorExit (i, HD63450.DMA_TIMING_ERROR);
  3058:            return;
  3059:          }
  3060:          HD63450.dmaMFC[i] = d & HD63450.DMA_FC2;
  3061:          if (DataBreakPoint.DBP_ON) {
  3062:            HD63450.dmaMFCMap[i] = HD63450.dmaMFC[i] == 0 ? DataBreakPoint.dbpUserMap : DataBreakPoint.dbpSuperMap;
  3063:          } else {
  3064:            HD63450.dmaMFCMap[i] = HD63450.dmaMFC[i] == 0 ? XEiJ.busUserMap : XEiJ.busSuperMap;
  3065:          }
  3066:          return;
  3067:        case HD63450.DMA_CPR:
  3068:          HD63450.dmaCP[i] = d & HD63450.DMA_CP;
  3069:          return;
  3070:        case HD63450.DMA_DFC:
  3071:          if (HD63450.dmaACT[i] != 0) {
  3072:            HD63450.dmaErrorExit (i, HD63450.DMA_TIMING_ERROR);
  3073:            return;
  3074:          }
  3075:          HD63450.dmaDFC[i] = d & HD63450.DMA_FC2;
  3076:          if (DataBreakPoint.DBP_ON) {
  3077:            HD63450.dmaDFCMap[i] = HD63450.dmaDFC[i] == 0 ? DataBreakPoint.dbpUserMap : DataBreakPoint.dbpSuperMap;
  3078:          } else {
  3079:            HD63450.dmaDFCMap[i] = HD63450.dmaDFC[i] == 0 ? XEiJ.busUserMap : XEiJ.busSuperMap;
  3080:          }
  3081:          return;
  3082:        case HD63450.DMA_BFC:
  3083:          HD63450.dmaBFC[i] = d & HD63450.DMA_FC2;
  3084:          if (DataBreakPoint.DBP_ON) {
  3085:            HD63450.dmaBFCMap[i] = HD63450.dmaBFC[i] == 0 ? DataBreakPoint.dbpUserMap : DataBreakPoint.dbpSuperMap;
  3086:          } else {
  3087:            HD63450.dmaBFCMap[i] = HD63450.dmaBFC[i] == 0 ? XEiJ.busUserMap : XEiJ.busSuperMap;
  3088:          }
  3089:          return;
  3090:        default:
  3091:          return;
  3092:        }
  3093:      }
  3094:     @Override protected void mmdWw (int a, int d) throws M68kException {
  3095:        a &= XEiJ.BUS_MOTHER_MASK;
  3096:        int al = a & 255;
  3097:        int i = al >> 6;  //チャンネル
  3098:        if (HD63450.DMA_DEBUG_TRACE != 0 && (HD63450.DMA_DEBUG_TRACE & 1 << i) != 0) {
  3099:          System.out.printf ("%d %08x HD63450.dmaWw(0x%08x,0x%04x)\n", XEiJ.mpuClockTime, XEiJ.regPC0, a, d);
  3100:        }
  3101:        switch (al & 0x3f) {
  3102:        case HD63450.DMA_MTC:
  3103:          if (HD63450.dmaACT[i] != 0) {
  3104:            HD63450.dmaErrorExit (i, HD63450.DMA_TIMING_ERROR);
  3105:            return;
  3106:          }
  3107:          HD63450.dmaMTC[i] = (char) d;
  3108:          return;
  3109:        case HD63450.DMA_MAR:
  3110:          if (HD63450.dmaACT[i] != 0) {
  3111:            HD63450.dmaErrorExit (i, HD63450.DMA_TIMING_ERROR);
  3112:            return;
  3113:          }
  3114:          HD63450.dmaMAR[i] = d << 16 | (char) HD63450.dmaMAR[i];
  3115:          return;
  3116:        case HD63450.DMA_MAR + 2:
  3117:          if (HD63450.dmaACT[i] != 0) {
  3118:            HD63450.dmaErrorExit (i, HD63450.DMA_TIMING_ERROR);
  3119:            return;
  3120:          }
  3121:          HD63450.dmaMAR[i] = ~0xffff & HD63450.dmaMAR[i] | (char) d;
  3122:          return;
  3123:        case HD63450.DMA_DAR:
  3124:          if (HD63450.dmaACT[i] != 0) {
  3125:            HD63450.dmaErrorExit (i, HD63450.DMA_TIMING_ERROR);
  3126:            return;
  3127:          }
  3128:          HD63450.dmaDAR[i] = d << 16 | (char) HD63450.dmaDAR[i];
  3129:          return;
  3130:        case HD63450.DMA_DAR + 2:
  3131:          if (HD63450.dmaACT[i] != 0) {
  3132:            HD63450.dmaErrorExit (i, HD63450.DMA_TIMING_ERROR);
  3133:            return;
  3134:          }
  3135:          HD63450.dmaDAR[i] = ~0xffff & HD63450.dmaDAR[i] | (char) d;
  3136:          return;
  3137:        case HD63450.DMA_BTC:
  3138:          HD63450.dmaBTC[i] = (char) d;
  3139:          return;
  3140:        case HD63450.DMA_BAR:
  3141:          HD63450.dmaBAR[i] = d << 16 | (char) HD63450.dmaBAR[i];
  3142:          return;
  3143:        case HD63450.DMA_BAR + 2:
  3144:          HD63450.dmaBAR[i] = ~0xffff & HD63450.dmaBAR[i] | (char) d;
  3145:          return;
  3146:        }
  3147:        mmdWb (a    , d >> 8);
  3148:        mmdWb (a + 1, d     );
  3149:      }
  3150:     @Override protected void mmdWl (int a, int d) throws M68kException {
  3151:        a &= XEiJ.BUS_MOTHER_MASK;
  3152:        int al = a & 255;
  3153:        int i = al >> 6;  //チャンネル
  3154:        if (HD63450.DMA_DEBUG_TRACE != 0 && (HD63450.DMA_DEBUG_TRACE & 1 << i) != 0) {
  3155:          System.out.printf ("%d %08x HD63450.dmaWl(0x%08x,0x%08x)\n", XEiJ.mpuClockTime, XEiJ.regPC0, a, d);
  3156:        }
  3157:        switch (al & 0x3f) {
  3158:        case HD63450.DMA_MAR:
  3159:          if (HD63450.dmaACT[i] != 0) {
  3160:            HD63450.dmaErrorExit (i, HD63450.DMA_TIMING_ERROR);
  3161:            return;
  3162:          }
  3163:          HD63450.dmaMAR[i] = d;
  3164:          return;
  3165:        case HD63450.DMA_DAR:
  3166:          if (HD63450.dmaACT[i] != 0) {
  3167:            HD63450.dmaErrorExit (i, HD63450.DMA_TIMING_ERROR);
  3168:            return;
  3169:          }
  3170:          HD63450.dmaDAR[i] = d;
  3171:          return;
  3172:        case HD63450.DMA_BAR:
  3173:          HD63450.dmaBAR[i] = d;
  3174:          return;
  3175:        }
  3176:        mmdWw (a    , d >> 16);
  3177:        mmdWw (a + 2, d      );
  3178:      }
  3179:   },  //MMD_DMA
  3180: 
  3181:   //--------------------------------------------------------------------------------
  3182:   //MMD_SVS スーパーバイザ領域設定
  3183:   MMD_SVS {
  3184:     @Override public String toString () {
  3185:       return Multilingual.mlnJapanese ? "スーパーバイザ領域設定" : "Supervisor Area Setting";
  3186:     }
  3187:     //ライト
  3188:     @Override protected void mmdWb (int a, int d) throws M68kException {
  3189:        a &= XEiJ.BUS_MOTHER_MASK;
  3190:        if (a == XEiJ.SVS_AREASET) {
  3191:          a = (0xff & d) + 1 << 13;
  3192:          XEiJ.busSuper (MemoryMappedDevice.MMD_MMR, 0x00000000, a);
  3193:          XEiJ.busUser ( MemoryMappedDevice.MMD_MMR, a, Math.min (0x00200000, MainMemory.mmrMemorySizeCurrent));
  3194:          return;
  3195:        }
  3196:      }
  3197:     @Override protected void mmdWw (int a, int d) throws M68kException {
  3198:        a &= XEiJ.BUS_MOTHER_MASK;
  3199:        mmdWb (a    , d >> 8);
  3200:        mmdWb (a + 1, d     );
  3201:      }
  3202:     @Override protected void mmdWl (int a, int d) throws M68kException {
  3203:        a &= XEiJ.BUS_MOTHER_MASK;
  3204:        mmdWw (a    , d >> 16);
  3205:        mmdWw (a + 2, d      );
  3206:      }
  3207:   },  //MMD_SVS
  3208: 
  3209:   //--------------------------------------------------------------------------------
  3210:   //MMD_MFP MFP
  3211:   MMD_MFP {
  3212:     @Override public String toString () {
  3213:       return Multilingual.mlnJapanese ? "MFP" : "MFP";  //Multi Function Peripheral
  3214:     }
  3215:     //ピーク
  3216:     @Override protected byte mmdPbs (int a) {
  3217:       a &= XEiJ.BUS_MOTHER_MASK;
  3218:       return (byte) mmdPbz (a);
  3219:     }
  3220:     @Override protected int mmdPbz (int a) {
  3221:       a &= XEiJ.BUS_MOTHER_MASK;
  3222:       try {
  3223:         return a == MC68901.MFP_UDR ? MC68901.mfpUdrQueueArray[MC68901.mfpUdrQueueRead] : mmdRbz (a);
  3224:       } catch (M68kException e) {
  3225:       }
  3226:       return 0;
  3227:     }
  3228:     @Override protected int mmdPws (int a) {
  3229:       a &= XEiJ.BUS_MOTHER_MASK;
  3230:       return (short) (mmdPbz (a) << 8 | mmdPbz (a + 1));
  3231:     }
  3232:     @Override protected int mmdPwz (int a) {
  3233:       a &= XEiJ.BUS_MOTHER_MASK;
  3234:       return mmdPbz (a) << 8 | mmdPbz (a + 1);
  3235:     }
  3236:     @Override protected int mmdPls (int a) {
  3237:       a &= XEiJ.BUS_MOTHER_MASK;
  3238:       return mmdPwz (a) << 16 | mmdPwz (a + 2);
  3239:     }
  3240:     //リード
  3241:     @Override protected int mmdRbz (int a) throws M68kException {
  3242:        a &= XEiJ.BUS_MOTHER_MASK;
  3243:        switch (a) {
  3244:        case MC68901.MFP_GPIP_DATA:
  3245:          return MC68901.mfpGpipHsync | MC68901.mfpGpipRint | 0b00100000 | MC68901.mfpGpipVdisp | MC68901.mfpGpipOpmirq | MC68901.mfpGpipPower | MC68901.mfpGpipExpwon | MC68901.mfpGpipAlarm;  //GPIP5は常に1
  3246:        case MC68901.MFP_AER:
  3247:          return MC68901.mfpAer;
  3248:        case MC68901.MFP_DDR:
  3249:          return 0x00;
  3250:        case MC68901.MFP_IERA:
  3251:          return MC68901.mfpIer >>> 8;
  3252:        case MC68901.MFP_IERB:
  3253:          return 0xff & MC68901.mfpIer;
  3254:        case MC68901.MFP_IPRA:
  3255:          return ((MC68901.mfpInnerRequest[15] != MC68901.mfpInnerAcknowledged[15] ? 0b10000000 : 0) |
  3256:                  (MC68901.mfpInnerRequest[14] != MC68901.mfpInnerAcknowledged[14] ? 0b01000000 : 0) |
  3257:                  (MC68901.mfpInnerRequest[13] != MC68901.mfpInnerAcknowledged[13] ? 0b00100000 : 0) |
  3258:                  (MC68901.mfpInnerRequest[12] != MC68901.mfpInnerAcknowledged[12] ? 0b00010000 : 0) |
  3259:                  (MC68901.mfpInnerRequest[11] != MC68901.mfpInnerAcknowledged[11] ? 0b00001000 : 0) |
  3260:                  (MC68901.mfpInnerRequest[10] != MC68901.mfpInnerAcknowledged[10] ? 0b00000100 : 0) |
  3261:                  (MC68901.mfpInnerRequest[ 9] != MC68901.mfpInnerAcknowledged[ 9] ? 0b00000010 : 0) |
  3262:                  (MC68901.mfpInnerRequest[ 8] != MC68901.mfpInnerAcknowledged[ 8] ? 0b00000001 : 0));
  3263:        case MC68901.MFP_IPRB:
  3264:          return ((MC68901.mfpInnerRequest[ 7] != MC68901.mfpInnerAcknowledged[ 7] ? 0b10000000 : 0) |
  3265:                  (MC68901.mfpInnerRequest[ 6] != MC68901.mfpInnerAcknowledged[ 6] ? 0b01000000 : 0) |
  3266:                  (MC68901.mfpInnerRequest[ 5] != MC68901.mfpInnerAcknowledged[ 5] ? 0b00100000 : 0) |
  3267:                  (MC68901.mfpInnerRequest[ 4] != MC68901.mfpInnerAcknowledged[ 4] ? 0b00010000 : 0) |
  3268:                  (MC68901.mfpInnerRequest[ 3] != MC68901.mfpInnerAcknowledged[ 3] ? 0b00001000 : 0) |
  3269:                  (MC68901.mfpInnerRequest[ 2] != MC68901.mfpInnerAcknowledged[ 2] ? 0b00000100 : 0) |
  3270:                  (MC68901.mfpInnerRequest[ 1] != MC68901.mfpInnerAcknowledged[ 1] ? 0b00000010 : 0) |
  3271:                  (MC68901.mfpInnerRequest[ 0] != MC68901.mfpInnerAcknowledged[ 0] ? 0b00000001 : 0));
  3272:        case MC68901.MFP_ISRA:
  3273:          return ((MC68901.mfpInnerInService[15] ? 0b10000000 : 0) |
  3274:                  (MC68901.mfpInnerInService[14] ? 0b01000000 : 0) |
  3275:                  (MC68901.mfpInnerInService[13] ? 0b00100000 : 0) |
  3276:                  (MC68901.mfpInnerInService[12] ? 0b00010000 : 0) |
  3277:                  (MC68901.mfpInnerInService[11] ? 0b00001000 : 0) |
  3278:                  (MC68901.mfpInnerInService[10] ? 0b00000100 : 0) |
  3279:                  (MC68901.mfpInnerInService[ 9] ? 0b00000010 : 0) |
  3280:                  (MC68901.mfpInnerInService[ 8] ? 0b00000001 : 0));
  3281:        case MC68901.MFP_ISRB:
  3282:          return ((MC68901.mfpInnerInService[ 7] ? 0b10000000 : 0) |
  3283:                  (MC68901.mfpInnerInService[ 6] ? 0b01000000 : 0) |
  3284:                  (MC68901.mfpInnerInService[ 5] ? 0b00100000 : 0) |
  3285:                  (MC68901.mfpInnerInService[ 4] ? 0b00010000 : 0) |
  3286:                  (MC68901.mfpInnerInService[ 3] ? 0b00001000 : 0) |
  3287:                  (MC68901.mfpInnerInService[ 2] ? 0b00000100 : 0) |
  3288:                  (MC68901.mfpInnerInService[ 1] ? 0b00000010 : 0) |
  3289:                  (MC68901.mfpInnerInService[ 0] ? 0b00000001 : 0));
  3290:        case MC68901.MFP_IMRA:
  3291:          return MC68901.mfpImr >>> 8;
  3292:        case MC68901.MFP_IMRB:
  3293:          return MC68901.mfpImr & 255;
  3294:        case MC68901.MFP_VECTOR:
  3295:          return MC68901.mfpVectorHigh;
  3296:        case MC68901.MFP_TACR:
  3297:          return (MC68901.mfpTaEventcount ? 0x08 : 0) | MC68901.mfpTaPrescale;
  3298:        case MC68901.MFP_TBCR:
  3299:          return 0x01;  //固定
  3300:        case MC68901.MFP_TCDCR:
  3301:          return MC68901.mfpTcPrescale << 4 | MC68901.mfpTdPrescale;
  3302:        case MC68901.MFP_TADR:
  3303:          if (MC68901.mfpTaEventcount || MC68901.mfpTaPrescale == 0) {
  3304:            return 0xff & MC68901.mfpTaCurrent;
  3305:          }
  3306:          return MC68901.mfpTaInitial - (int) (Math.floor ((double) (XEiJ.mpuClockTime - MC68901.mfpTaStart) / MC68901.mfpTaDelta) % MC68901.mfpTaInitial) & 255;
  3307:        case MC68901.MFP_TBDR:
  3308:          return 0;  //乱数にしたほうがいいかも
  3309:        case MC68901.MFP_TCDR:
  3310:          if (MC68901.mfpTcPrescale == 0) {
  3311:            return MC68901.mfpTcCurrent & 255;
  3312:          }
  3313:          return MC68901.mfpTcInitial - (int) (Math.floor ((double) (XEiJ.mpuClockTime - MC68901.mfpTcStart) / MC68901.mfpTcDelta) % MC68901.mfpTcInitial) & 255;
  3314:        case MC68901.MFP_TDDR:
  3315:          if (MC68901.mfpTdPrescale == 0) {
  3316:            return MC68901.mfpTdCurrent & 255;
  3317:          }
  3318:          return MC68901.mfpTdInitial - (int) (Math.floor ((double) (XEiJ.mpuClockTime - MC68901.mfpTdStart) / MC68901.mfpTdDelta) % MC68901.mfpTdInitial) & 255;
  3319:        case MC68901.MFP_SYNC_CHAR:
  3320:          return 0;
  3321:        case MC68901.MFP_UCR:
  3322:          return 0;
  3323:        case MC68901.MFP_RSR:
  3324:          if (MC68901.MFP_KBD_ON) {
  3325:            return MC68901.mfpKbdReadPointer != MC68901.mfpKbdWritePointer ? 0x80 : 0;
  3326:          } else {
  3327:            return MC68901.mfpUdrQueueRead != MC68901.mfpUdrQueueWrite ? 0x80 : 0;
  3328:          }
  3329:        case MC68901.MFP_TSR:
  3330:          return 0x80;  //バッファエンプティ
  3331:        case MC68901.MFP_UDR:
  3332:          if (MC68901.MFP_KBD_ON) {
  3333:            return MC68901.mfpKbdReadData ();
  3334:          } else {
  3335:            if (MC68901.mfpUdrQueueRead != MC68901.mfpUdrQueueWrite) {  //キューが空でないとき
  3336:              MC68901.mfpUdrQueueRead = MC68901.mfpUdrQueueRead + 1 & MC68901.MFP_UDR_QUEUE_MASK;
  3337:              if (MC68901.mfpUdrQueueRead != MC68901.mfpUdrQueueWrite) {  //キューが空にならなければ再度割り込み要求を出す
  3338:                if ((MC68901.mfpIer & MC68901.MFP_INPUT_FULL_MASK) != 0) {
  3339:                  MC68901.mfpInnerRequest[MC68901.MFP_INPUT_FULL_LEVEL]++;
  3340:                  if ((MC68901.mfpImr & MC68901.MFP_INPUT_FULL_MASK) != 0) {
  3341:                    if (MC68901.MFP_DELAYED_INTERRUPT) {
  3342:                      XEiJ.mpuDIRR |= XEiJ.MPU_MFP_INTERRUPT_MASK;
  3343:                    } else {
  3344:                      XEiJ.mpuIRR |= XEiJ.MPU_MFP_INTERRUPT_MASK;
  3345:                    }
  3346:                  }
  3347:                }
  3348:              }
  3349:            }
  3350:            return MC68901.mfpUdrQueueArray[MC68901.mfpUdrQueueRead];  //最後に押されたまたは離されたキー
  3351:          }
  3352:        }
  3353:        return 0xff;
  3354:      }
  3355:     @Override protected int mmdRwz (int a) throws M68kException {
  3356:        a &= XEiJ.BUS_MOTHER_MASK;
  3357:        return mmdRbz (a) << 8 | mmdRbz (a + 1);
  3358:      }
  3359:     @Override protected int mmdRls (int a) throws M68kException {
  3360:        a &= XEiJ.BUS_MOTHER_MASK;
  3361:        return mmdRwz (a) << 16 | mmdRwz (a + 2);
  3362:      }
  3363:     //ライト
  3364:     @Override protected void mmdWb (int a, int d) throws M68kException {
  3365:        a &= XEiJ.BUS_MOTHER_MASK;
  3366:        switch (a) {
  3367:        case MC68901.MFP_GPIP_DATA:
  3368:          return;
  3369:        case MC68901.MFP_AER:
  3370:          MC68901.mfpAer = 0xff & d;
  3371:          return;
  3372:        case MC68901.MFP_DDR:
  3373:          return;
  3374:        case MC68901.MFP_IERA:
  3375:          d = (char) (d << 8);
  3376:          int oldIera = MC68901.mfpIer;
  3377:          MC68901.mfpIer = d | 0x00ff & MC68901.mfpIer;
  3378:          //MC68901.MFP_IERAのビットに0を書き込むとMC68901.MFP_IPRAの該当ビットも0になる
  3379:          if ((short) d >= 0) {  //(0b10000000_00000000 & d) == 0
  3380:            MC68901.mfpInnerAcknowledged[15] = MC68901.mfpInnerRequest[15];
  3381:          }
  3382:          if (d << 31 - 14 >= 0) {  //(0b01000000_00000000 & d) == 0
  3383:            MC68901.mfpInnerAcknowledged[14] = MC68901.mfpInnerRequest[14];
  3384:          }
  3385:          if (d << 31 - 13 >= 0) {  //(0b00100000_00000000 & d) == 0
  3386:            MC68901.mfpInnerAcknowledged[13] = MC68901.mfpInnerRequest[13];
  3387:          }
  3388:          if (d << 31 - 12 >= 0) {  //(0b00010000_00000000 & d) == 0
  3389:            MC68901.mfpInnerAcknowledged[12] = MC68901.mfpInnerRequest[12];
  3390:          } else if (oldIera << 31 - 12 >= 0 &&  //MC68901.MFP_INPUT_FULL_MASKが0→1
  3391:                     (MC68901.MFP_KBD_ON ?
  3392:                      MC68901.mfpKbdReadPointer != MC68901.mfpKbdWritePointer :  //バッファが空でないとき
  3393:                      MC68901.mfpUdrQueueRead != MC68901.mfpUdrQueueWrite)) {  //キューが空でないとき
  3394:            MC68901.mfpInnerRequest[MC68901.MFP_INPUT_FULL_LEVEL]++;
  3395:            if ((MC68901.mfpImr & MC68901.MFP_INPUT_FULL_MASK) != 0) {
  3396:              //MFPのキー入力割り込みを要求する
  3397:              if (MC68901.MFP_DELAYED_INTERRUPT) {
  3398:                XEiJ.mpuDIRR |= XEiJ.MPU_MFP_INTERRUPT_MASK;
  3399:              } else {
  3400:                XEiJ.mpuIRR |= XEiJ.MPU_MFP_INTERRUPT_MASK;
  3401:              }
  3402:            }
  3403:          }
  3404:          if (d << 31 - 11 >= 0) {  //(0b00001000_00000000 & d) == 0
  3405:            MC68901.mfpInnerAcknowledged[11] = MC68901.mfpInnerRequest[11];
  3406:          }
  3407:          if (d << 31 - 10 >= 0) {  //(0b00000100_00000000 & d) == 0
  3408:            MC68901.mfpInnerAcknowledged[10] = MC68901.mfpInnerRequest[10];
  3409:          }
  3410:          if (d << 31 - 9 >= 0) {  //(0b00000010_00000000 & d) == 0
  3411:            MC68901.mfpInnerAcknowledged[ 9] = MC68901.mfpInnerRequest[ 9];
  3412:          }
  3413:          if (d << 31 - 8 >= 0) {  //(0b00000001_00000000 & d) == 0
  3414:            MC68901.mfpInnerAcknowledged[ 8] = MC68901.mfpInnerRequest[ 8];
  3415:          }
  3416:          return;
  3417:        case MC68901.MFP_IERB:
  3418:          MC68901.mfpIer = ~0xff & MC68901.mfpIer | 0xff & d;
  3419:          //MC68901.MFP_IERBのビットに0を書き込むとMC68901.MFP_IPRBの該当ビットも0になる
  3420:          if ((byte) d >= 0) {  //(0b10000000 & d) == 0
  3421:            MC68901.mfpInnerAcknowledged[ 7] = MC68901.mfpInnerRequest[ 7];
  3422:          }
  3423:          if (d << 31 - 6 >= 0) {  //(0b01000000 & d) == 0
  3424:            MC68901.mfpInnerAcknowledged[ 6] = MC68901.mfpInnerRequest[ 6];
  3425:          }
  3426:          if (d << 31 - 5 >= 0) {  //(0b00100000 & d) == 0
  3427:            MC68901.mfpInnerAcknowledged[ 5] = MC68901.mfpInnerRequest[ 5];
  3428:          }
  3429:          if (d << 31 - 4 >= 0) {  //(0b00010000 & d) == 0
  3430:            MC68901.mfpInnerAcknowledged[ 4] = MC68901.mfpInnerRequest[ 4];
  3431:          }
  3432:          if (XEiJ.TEST_BIT_3_SHIFT ? d << 31 - 3 >= 0 : (d & 8) == 0) {
  3433:            MC68901.mfpInnerAcknowledged[ 3] = MC68901.mfpInnerRequest[ 3];
  3434:          }
  3435:          if (XEiJ.TEST_BIT_2_SHIFT ? d << 31 - 2 >= 0 : (d & 4) == 0) {
  3436:            MC68901.mfpInnerAcknowledged[ 2] = MC68901.mfpInnerRequest[ 2];
  3437:          }
  3438:          if (XEiJ.TEST_BIT_1_SHIFT ? d << 31 - 1 >= 0 : (d & 2) == 0) {
  3439:            MC68901.mfpInnerAcknowledged[ 1] = MC68901.mfpInnerRequest[ 1];
  3440:          }
  3441:          if (XEiJ.TEST_BIT_0_SHIFT ? d << 31 - 0 >= 0 : (d & 1) == 0) {
  3442:            MC68901.mfpInnerAcknowledged[ 0] = MC68901.mfpInnerRequest[ 0];
  3443:          }
  3444:          return;
  3445:        case MC68901.MFP_IPRA:
  3446:          //MC68901.MFP_IPRAのビットは他のすべてのビットに1を書き込むことで直接クリアできる
  3447:          switch (0xff & d) {
  3448:          case 0b01111111:
  3449:            MC68901.mfpInnerAcknowledged[15] = MC68901.mfpInnerRequest[15];
  3450:            break;
  3451:          case 0b10111111:
  3452:            MC68901.mfpInnerAcknowledged[14] = MC68901.mfpInnerRequest[14];
  3453:            break;
  3454:          case 0b11011111:
  3455:            MC68901.mfpInnerAcknowledged[13] = MC68901.mfpInnerRequest[13];
  3456:            break;
  3457:          case 0b11101111:
  3458:            MC68901.mfpInnerAcknowledged[12] = MC68901.mfpInnerRequest[12];
  3459:            break;
  3460:          case 0b11110111:
  3461:            MC68901.mfpInnerAcknowledged[11] = MC68901.mfpInnerRequest[11];
  3462:            break;
  3463:          case 0b11111011:
  3464:            MC68901.mfpInnerAcknowledged[10] = MC68901.mfpInnerRequest[10];
  3465:            break;
  3466:          case 0b11111101:
  3467:            MC68901.mfpInnerAcknowledged[ 9] = MC68901.mfpInnerRequest[ 9];
  3468:            break;
  3469:          case 0b11111110:
  3470:            MC68901.mfpInnerAcknowledged[ 8] = MC68901.mfpInnerRequest[ 8];
  3471:            break;
  3472:          }
  3473:          return;
  3474:        case MC68901.MFP_IPRB:
  3475:          //MC68901.MFP_IPRBのビットは他のすべてのビットに1を書き込むことで直接クリアできる
  3476:          switch (0xff & d) {
  3477:          case 0b01111111:
  3478:            MC68901.mfpInnerAcknowledged[ 7] = MC68901.mfpInnerRequest[ 7];
  3479:            break;
  3480:          case 0b10111111:
  3481:            MC68901.mfpInnerAcknowledged[ 6] = MC68901.mfpInnerRequest[ 6];
  3482:            break;
  3483:          case 0b11011111:
  3484:            MC68901.mfpInnerAcknowledged[ 5] = MC68901.mfpInnerRequest[ 5];
  3485:            break;
  3486:          case 0b11101111:
  3487:            MC68901.mfpInnerAcknowledged[ 4] = MC68901.mfpInnerRequest[ 4];
  3488:            break;
  3489:          case 0b11110111:
  3490:            MC68901.mfpInnerAcknowledged[ 3] = MC68901.mfpInnerRequest[ 3];
  3491:            break;
  3492:          case 0b11111011:
  3493:            MC68901.mfpInnerAcknowledged[ 2] = MC68901.mfpInnerRequest[ 2];
  3494:            break;
  3495:          case 0b11111101:
  3496:            MC68901.mfpInnerAcknowledged[ 1] = MC68901.mfpInnerRequest[ 1];
  3497:            break;
  3498:          case 0b11111110:
  3499:            MC68901.mfpInnerAcknowledged[ 0] = MC68901.mfpInnerRequest[ 0];
  3500:            break;
  3501:          }
  3502:          return;
  3503:        case MC68901.MFP_ISRA:
  3504:          //MC68901.MFP_ISRAのビットは他のすべてのビットに1を書き込むことで直接クリアできる
  3505:          switch (0xff & d) {
  3506:          case 0b01111111:
  3507:            MC68901.mfpInnerInService[15] = false;
  3508:            break;
  3509:          case 0b10111111:
  3510:            MC68901.mfpInnerInService[14] = false;
  3511:            break;
  3512:          case 0b11011111:
  3513:            MC68901.mfpInnerInService[13] = false;
  3514:            break;
  3515:          case 0b11101111:
  3516:            MC68901.mfpInnerInService[12] = false;
  3517:            break;
  3518:          case 0b11110111:
  3519:            MC68901.mfpInnerInService[11] = false;
  3520:            break;
  3521:          case 0b11111011:
  3522:            MC68901.mfpInnerInService[10] = false;
  3523:            break;
  3524:          case 0b11111101:
  3525:            MC68901.mfpInnerInService[ 9] = false;
  3526:            break;
  3527:          case 0b11111110:
  3528:            MC68901.mfpInnerInService[ 8] = false;
  3529:            break;
  3530:          }
  3531:          return;
  3532:        case MC68901.MFP_ISRB:
  3533:          //MC68901.MFP_ISRBのビットは他のすべてのビットに1を書き込むことで直接クリアできる
  3534:          switch (0xff & d) {
  3535:          case 0b01111111:
  3536:            MC68901.mfpInnerInService[ 7] = false;
  3537:            break;
  3538:          case 0b10111111:
  3539:            MC68901.mfpInnerInService[ 6] = false;
  3540:            break;
  3541:          case 0b11011111:
  3542:            MC68901.mfpInnerInService[ 5] = false;
  3543:            break;
  3544:          case 0b11101111:
  3545:            MC68901.mfpInnerInService[ 4] = false;
  3546:            break;
  3547:          case 0b11110111:
  3548:            MC68901.mfpInnerInService[ 3] = false;
  3549:            break;
  3550:          case 0b11111011:
  3551:            MC68901.mfpInnerInService[ 2] = false;
  3552:            break;
  3553:          case 0b11111101:
  3554:            MC68901.mfpInnerInService[ 1] = false;
  3555:            break;
  3556:          case 0b11111110:
  3557:            MC68901.mfpInnerInService[ 0] = false;
  3558:            break;
  3559:          }
  3560:          return;
  3561:        case MC68901.MFP_IMRA:
  3562:          MC68901.mfpImr = (0xff & d) << 8 | 0xff & MC68901.mfpImr;
  3563:          //MC68901.MFP_IMRAのビットに1を書き込んだときMC68901.MFP_IPRAの該当ビットが1ならば割り込み発生
  3564:          if ((byte) d < 0 && MC68901.mfpInnerRequest[15] != MC68901.mfpInnerAcknowledged[15] ||  //(0b10000000 & d) != 0
  3565:              d << 31 - 6 < 0 && MC68901.mfpInnerRequest[14] != MC68901.mfpInnerAcknowledged[14] ||  //(0b01000000 & d) != 0
  3566:              d << 31 - 5 < 0 && MC68901.mfpInnerRequest[13] != MC68901.mfpInnerAcknowledged[13] ||  //(0b00100000 & d) != 0
  3567:              d << 31 - 4 < 0 && MC68901.mfpInnerRequest[12] != MC68901.mfpInnerAcknowledged[12] ||  //(0b00010000 & d) != 0
  3568:              (XEiJ.TEST_BIT_3_SHIFT ? d << 31 - 3 < 0 : (d & 8) != 0) && MC68901.mfpInnerRequest[11] != MC68901.mfpInnerAcknowledged[11] ||
  3569:              (XEiJ.TEST_BIT_2_SHIFT ? d << 31 - 2 < 0 : (d & 4) != 0) && MC68901.mfpInnerRequest[10] != MC68901.mfpInnerAcknowledged[10] ||
  3570:              (XEiJ.TEST_BIT_1_SHIFT ? d << 31 - 1 < 0 : (d & 2) != 0) && MC68901.mfpInnerRequest[ 9] != MC68901.mfpInnerAcknowledged[ 9] ||
  3571:              (XEiJ.TEST_BIT_0_SHIFT ? d << 31 - 0 < 0 : (d & 1) != 0) && MC68901.mfpInnerRequest[ 8] != MC68901.mfpInnerAcknowledged[ 8]) {
  3572:            if (MC68901.MFP_DELAYED_INTERRUPT) {
  3573:              XEiJ.mpuDIRR |= XEiJ.MPU_MFP_INTERRUPT_MASK;
  3574:            } else {
  3575:              XEiJ.mpuIRR |= XEiJ.MPU_MFP_INTERRUPT_MASK;
  3576:            }
  3577:          }
  3578:          return;
  3579:        case MC68901.MFP_IMRB:
  3580:          MC68901.mfpImr = ~0xff & MC68901.mfpImr | 0xff & d;
  3581:          //MC68901.MFP_IMRBのビットに1を書き込んだときMC68901.MFP_IPRBの該当ビットが1ならば割り込み発生
  3582:          if ((byte) d < 0 && MC68901.mfpInnerRequest[ 7] != MC68901.mfpInnerAcknowledged[ 7] ||  //(0b10000000 & d) != 0
  3583:              d << 31 - 6 < 0 && MC68901.mfpInnerRequest[ 6] != MC68901.mfpInnerAcknowledged[ 6] ||  //(0b01000000 & d) != 0
  3584:              d << 31 - 5 < 0 && MC68901.mfpInnerRequest[ 5] != MC68901.mfpInnerAcknowledged[ 5] ||  //(0b00100000 & d) != 0
  3585:              d << 31 - 4 < 0 && MC68901.mfpInnerRequest[ 4] != MC68901.mfpInnerAcknowledged[ 4] ||  //(0b00010000 & d) != 0
  3586:              (XEiJ.TEST_BIT_3_SHIFT ? d << 31 - 3 < 0 : (d & 8) != 0) && MC68901.mfpInnerRequest[ 3] != MC68901.mfpInnerAcknowledged[ 3] ||
  3587:              (XEiJ.TEST_BIT_2_SHIFT ? d << 31 - 2 < 0 : (d & 4) != 0) && MC68901.mfpInnerRequest[ 2] != MC68901.mfpInnerAcknowledged[ 2] ||
  3588:              (XEiJ.TEST_BIT_1_SHIFT ? d << 31 - 1 < 0 : (d & 2) != 0) && MC68901.mfpInnerRequest[ 1] != MC68901.mfpInnerAcknowledged[ 1] ||
  3589:              (XEiJ.TEST_BIT_0_SHIFT ? d << 31 - 0 < 0 : (d & 1) != 0) && MC68901.mfpInnerRequest[ 0] != MC68901.mfpInnerAcknowledged[ 0]) {
  3590:            if (MC68901.MFP_DELAYED_INTERRUPT) {
  3591:              XEiJ.mpuDIRR |= XEiJ.MPU_MFP_INTERRUPT_MASK;
  3592:            } else {
  3593:              XEiJ.mpuIRR |= XEiJ.MPU_MFP_INTERRUPT_MASK;
  3594:            }
  3595:          }
  3596:          return;
  3597:        case MC68901.MFP_VECTOR:
  3598:          MC68901.mfpVectorHigh = 0xf0 & d;  //ビット3は0(全チャンネル自動割込み終了モード)に固定
  3599:          return;
  3600:        case MC68901.MFP_TACR:
  3601:          {
  3602:            int prevPrescale = MC68901.mfpTaPrescale;
  3603:            MC68901.mfpTaEventcount = (d & 0x08) != 0;
  3604:            MC68901.mfpTaPrescale = d & 0x07;
  3605:            if (MC68901.mfpTaEventcount && MC68901.mfpTaPrescale != 0) {  //パルス幅計測モードはキャンセル
  3606:              MC68901.mfpTaEventcount = false;
  3607:              MC68901.mfpTaPrescale = 0;
  3608:            }
  3609:            if (MC68901.mfpTaEventcount) {  //イベントカウントモード
  3610:              if (prevPrescale != 0) {  //ディレイモードで動作中だったとき
  3611:                MC68901.mfpTaCurrent = MC68901.mfpTaInitial - (int) (Math.floor ((double) (XEiJ.mpuClockTime - MC68901.mfpTaStart) / MC68901.mfpTaDelta) % MC68901.mfpTaInitial);
  3612:              }
  3613:              MC68901.mfpTaClock = XEiJ.FAR_FUTURE;
  3614:              TickerQueue.tkqRemove (MC68901.mfpTaTicker);
  3615:            } else if (MC68901.mfpTaPrescale != 0) {  //ディレイモード
  3616:              //! ディレイモードで動作中にプリスケールを変更されるとカウンタが即座に初期値に戻ってしまう
  3617:              MC68901.mfpTaClock = (MC68901.mfpTaStart = XEiJ.mpuClockTime) + (MC68901.mfpTaDelta = MC68901.MFP_DELTA[MC68901.mfpTaPrescale]) * MC68901.mfpTaInitial;
  3618:              TickerQueue.tkqAdd (MC68901.mfpTaTicker, MC68901.mfpTaClock);
  3619:            } else {  //カウント停止
  3620:              if (prevPrescale != 0) {  //ディレイモードで動作中だったとき
  3621:                MC68901.mfpTaCurrent = MC68901.mfpTaInitial - (int) (Math.floor ((double) (XEiJ.mpuClockTime - MC68901.mfpTaStart) / MC68901.mfpTaDelta) % MC68901.mfpTaInitial);
  3622:              }
  3623:              MC68901.mfpTaClock = XEiJ.FAR_FUTURE;
  3624:              TickerQueue.tkqRemove (MC68901.mfpTaTicker);
  3625:            }
  3626:          }
  3627:          return;
  3628:        case MC68901.MFP_TBCR:
  3629:          //何もしない
  3630:          return;
  3631:        case MC68901.MFP_TCDCR:
  3632:          {
  3633:            int prevPrescale = MC68901.mfpTcPrescale;
  3634:            MC68901.mfpTcPrescale = d >> 4 & 0x07;
  3635:            if (MC68901.mfpTcPrescale != 0) {  //ディレイモード
  3636:              //! ディレイモードで動作中にプリスケールを変更されるとカウンタが即座に初期値に戻ってしまう
  3637:              MC68901.mfpTcClock = (MC68901.mfpTcStart = XEiJ.mpuClockTime) + (MC68901.mfpTcDelta = MC68901.MFP_DELTA[MC68901.mfpTcPrescale]) * MC68901.mfpTcInitial;
  3638:              TickerQueue.tkqAdd (MC68901.mfpTcTicker, MC68901.mfpTcClock);
  3639:            } else {  //カウント停止
  3640:              if (prevPrescale != 0) {  //ディレイモードで動作中だったとき
  3641:                MC68901.mfpTcCurrent = MC68901.mfpTcInitial - (int) (Math.floor ((double) (XEiJ.mpuClockTime - MC68901.mfpTcStart) / MC68901.mfpTcDelta) % MC68901.mfpTcInitial);
  3642:              }
  3643:              MC68901.mfpTcClock = XEiJ.FAR_FUTURE;
  3644:              TickerQueue.tkqRemove (MC68901.mfpTcTicker);
  3645:            }
  3646:          }
  3647:          {
  3648:            int prevPrescale = MC68901.mfpTdPrescale;
  3649:            MC68901.mfpTdPrescale = d & 0x07;
  3650:            if (MC68901.mfpTdPrescale != 0) {  //ディレイモード
  3651:              //! ディレイモードで動作中にプリスケールを変更されるとカウンタが即座に初期値に戻ってしまう
  3652:              MC68901.mfpTdClock = (MC68901.mfpTdStart = XEiJ.mpuClockTime) + (MC68901.mfpTdDelta = MC68901.MFP_DELTA[MC68901.mfpTdPrescale]) * MC68901.mfpTdInitial;
  3653:              TickerQueue.tkqAdd (MC68901.mfpTdTicker, MC68901.mfpTdClock);
  3654:            } else {  //カウント停止
  3655:              if (prevPrescale != 0) {  //ディレイモードで動作中だったとき
  3656:                MC68901.mfpTdCurrent = MC68901.mfpTdInitial - (int) (Math.floor ((double) (XEiJ.mpuClockTime - MC68901.mfpTdStart) / MC68901.mfpTdDelta) % MC68901.mfpTdInitial);
  3657:              }
  3658:              MC68901.mfpTdClock = XEiJ.FAR_FUTURE;
  3659:              TickerQueue.tkqRemove (MC68901.mfpTdTicker);
  3660:            }
  3661:          }
  3662:          return;
  3663:        case MC68901.MFP_TADR:
  3664:          //! ディレイモードで動作中に初期値を変更するとオーバーフローするまでMC68901.MFP_TADRの値がずれてしまう
  3665:          d &= 0xff;
  3666:          MC68901.mfpTaInitial = d == 0 ? 256 : d;  //初期値
  3667:          if (!MC68901.mfpTaEventcount && MC68901.mfpTaPrescale == 0) {  //動作中でなければカウンタの値も変更される
  3668:            MC68901.mfpTaCurrent = MC68901.mfpTaInitial;
  3669:          }
  3670:          return;
  3671:        case MC68901.MFP_TBDR:
  3672:          //何もしない
  3673:          return;
  3674:        case MC68901.MFP_TCDR:
  3675:          //! ディレイモードで動作中に初期値を変更するとオーバーフローするまでMC68901.MFP_TADRの値がずれてしまう
  3676:          d &= 0xff;
  3677:          MC68901.mfpTcInitial = d == 0 ? 256 : d;  //初期値
  3678:          if (MC68901.mfpTcPrescale == 0) {  //動作中でなければカウンタの値も変更される
  3679:            MC68901.mfpTcCurrent = MC68901.mfpTcInitial;
  3680:          }
  3681:          return;
  3682:        case MC68901.MFP_TDDR:
  3683:          //! ディレイモードで動作中に初期値を変更するとオーバーフローするまでMC68901.MFP_TADRの値がずれてしまう
  3684:          d &= 0xff;
  3685:          MC68901.mfpTdInitial = d == 0 ? 256 : d;  //初期値
  3686:          if (MC68901.mfpTdPrescale == 0) {  //動作中でなければカウンタの値も変更される
  3687:            MC68901.mfpTdCurrent = MC68901.mfpTdInitial;
  3688:          }
  3689:          return;
  3690:        case MC68901.MFP_SYNC_CHAR:
  3691:          return;
  3692:        case MC68901.MFP_UCR:
  3693:          return;
  3694:        case MC68901.MFP_RSR:
  3695:          return;
  3696:        case MC68901.MFP_TSR:
  3697:          return;
  3698:        case MC68901.MFP_UDR:
  3699:          if ((byte) d < 0) {  //LEDの状態
  3700:            Keyboard.kbdSetLedStatus (d);
  3701:          } else if ((d & 0xf8) == 0x40) {  //MSCTRL
  3702:          } else if ((d & 0xf8) == 0x48) {  //ロック
  3703:          } else if ((d & 0xfc) == 0x54) {  //LEDの明るさ
  3704:          } else if ((d & 0xfc) == 0x58) {  //テレビコントロール
  3705:          } else if ((d & 0xfc) == 0x5c) {  //OPT.2キーによるテレビコントロール
  3706:          } else if ((d & 0xf0) == 0x60) {  //リピート開始時間
  3707:            Keyboard.kbdSetRepeatDelay (0x0f & d);
  3708:          } else if ((d & 0xf0) == 0x70) {  //リピート間隔
  3709:            Keyboard.kbdSetRepeatInterval (0x0f & d);
  3710:          }
  3711:          return;
  3712:        }
  3713:      }
  3714:     @Override protected void mmdWw (int a, int d) throws M68kException {
  3715:        a &= XEiJ.BUS_MOTHER_MASK;
  3716:        mmdWb (a    , d >> 8);
  3717:        mmdWb (a + 1, d     );
  3718:      }
  3719:     @Override protected void mmdWl (int a, int d) throws M68kException {
  3720:        a &= XEiJ.BUS_MOTHER_MASK;
  3721:        mmdWw (a    , d >> 16);
  3722:        mmdWw (a + 2, d      );
  3723:      }
  3724:   },  //MMD_MFP
  3725: 
  3726:   //--------------------------------------------------------------------------------
  3727:   //MMD_RTC_FIRST RTC
  3728:   MMD_RTC_FIRST {
  3729:     @Override public String toString () {
  3730:       return Multilingual.mlnJapanese ? "RTC" : "RTC";  //Real-Time Clock
  3731:     }
  3732:     //ピーク
  3733:     @Override protected byte mmdPbs (int a) {
  3734:       return (byte) RP5C15.rtcPeekByte (a);
  3735:     }
  3736:     @Override protected int mmdPbz (int a) {
  3737:       return RP5C15.rtcPeekByte (a);
  3738:     }
  3739:     @Override protected int mmdPws (int a) {
  3740:       return RP5C15.rtcPeekByte (a + 1);
  3741:     }
  3742:     @Override protected int mmdPwz (int a) {
  3743:       return RP5C15.rtcPeekByte (a + 1);
  3744:     }
  3745:     @Override protected int mmdPls (int a) {
  3746:       return (RP5C15.rtcPeekByte (a + 1) << 16 |
  3747:               RP5C15.rtcPeekByte (a + 3));
  3748:     }
  3749:     //リード
  3750:     @Override protected byte mmdRbs (int a) throws M68kException {
  3751:        XEiJ.busSuper (MemoryMappedDevice.MMD_RTC_NEXT, 0x00e8a000, 0x00e8c000);  //RTC RTC
  3752:        RP5C15.rtcUpdate ();
  3753:        return (byte) RP5C15.rtcReadByte (a);
  3754:      }
  3755:     @Override protected int mmdRbz (int a) throws M68kException {
  3756:        XEiJ.busSuper (MemoryMappedDevice.MMD_RTC_NEXT, 0x00e8a000, 0x00e8c000);  //RTC RTC
  3757:        RP5C15.rtcUpdate ();
  3758:        return RP5C15.rtcReadByte (a);
  3759:      }
  3760:     @Override protected int mmdRws (int a) throws M68kException {
  3761:        XEiJ.busSuper (MemoryMappedDevice.MMD_RTC_NEXT, 0x00e8a000, 0x00e8c000);  //RTC RTC
  3762:        RP5C15.rtcUpdate ();
  3763:        return RP5C15.rtcReadByte (a + 1);
  3764:      }
  3765:     @Override protected int mmdRwz (int a) throws M68kException {
  3766:        XEiJ.busSuper (MemoryMappedDevice.MMD_RTC_NEXT, 0x00e8a000, 0x00e8c000);  //RTC RTC
  3767:        RP5C15.rtcUpdate ();
  3768:        return RP5C15.rtcReadByte (a + 1);
  3769:      }
  3770:     @Override protected int mmdRls (int a) throws M68kException {
  3771:        XEiJ.busSuper (MemoryMappedDevice.MMD_RTC_NEXT, 0x00e8a000, 0x00e8c000);  //RTC RTC
  3772:        RP5C15.rtcUpdate ();
  3773:        return (RP5C15.rtcReadByte (a + 1) << 16 |
  3774:                RP5C15.rtcReadByte (a + 3));
  3775:      }
  3776:     //ライト
  3777:     @Override protected void mmdWb (int a, int d) throws M68kException {
  3778:        XEiJ.busSuper (MemoryMappedDevice.MMD_RTC_NEXT, 0x00e8a000, 0x00e8c000);  //RTC RTC
  3779:        RP5C15.rtcUpdate ();
  3780:        RP5C15.rtcWriteByte (a, d);
  3781:      }
  3782:     @Override protected void mmdWw (int a, int d) throws M68kException {
  3783:        XEiJ.busSuper (MemoryMappedDevice.MMD_RTC_NEXT, 0x00e8a000, 0x00e8c000);  //RTC RTC
  3784:        RP5C15.rtcUpdate ();
  3785:        RP5C15.rtcWriteByte (a + 1, d);
  3786:      }
  3787:     @Override protected void mmdWl (int a, int d) throws M68kException {
  3788:        XEiJ.busSuper (MemoryMappedDevice.MMD_RTC_NEXT, 0x00e8a000, 0x00e8c000);  //RTC RTC
  3789:        RP5C15.rtcUpdate ();
  3790:        RP5C15.rtcWriteByte (a + 1, d >> 16);
  3791:        RP5C15.rtcWriteByte (a + 3, d);
  3792:      }
  3793:   },  //MMD_RTC_FIRST
  3794: 
  3795:   //--------------------------------------------------------------------------------
  3796:   //MMD_RTC_NEXT RTC
  3797:   MMD_RTC_NEXT {
  3798:     @Override public String toString () {
  3799:       return Multilingual.mlnJapanese ? "RTC" : "RTC";  //Real-Time Clock
  3800:     }
  3801:     //ピーク
  3802:     @Override protected byte mmdPbs (int a) {
  3803:       return (byte) RP5C15.rtcPeekByte (a);
  3804:     }
  3805:     @Override protected int mmdPbz (int a) {
  3806:       return RP5C15.rtcPeekByte (a);
  3807:     }
  3808:     @Override protected int mmdPws (int a) {
  3809:       return RP5C15.rtcPeekByte (a + 1);
  3810:     }
  3811:     @Override protected int mmdPwz (int a) {
  3812:       return RP5C15.rtcPeekByte (a + 1);
  3813:     }
  3814:     @Override protected int mmdPls (int a) {
  3815:       return (RP5C15.rtcPeekByte (a + 1) << 16 |
  3816:               RP5C15.rtcPeekByte (a + 3));
  3817:     }
  3818:     //リード
  3819:     @Override protected byte mmdRbs (int a) throws M68kException {
  3820:        return (byte) RP5C15.rtcReadByte (a);
  3821:      }
  3822:     @Override protected int mmdRbz (int a) throws M68kException {
  3823:        return RP5C15.rtcReadByte (a);
  3824:      }
  3825:     @Override protected int mmdRws (int a) throws M68kException {
  3826:        return RP5C15.rtcReadByte (a + 1);
  3827:      }
  3828:     @Override protected int mmdRwz (int a) throws M68kException {
  3829:        return RP5C15.rtcReadByte (a + 1);
  3830:      }
  3831:     @Override protected int mmdRls (int a) throws M68kException {
  3832:        return (RP5C15.rtcReadByte (a + 1) << 16 |
  3833:                RP5C15.rtcReadByte (a + 3));
  3834:      }
  3835:     //ライト
  3836:     @Override protected void mmdWb (int a, int d) throws M68kException {
  3837:        RP5C15.rtcWriteByte (a, d);
  3838:      }
  3839:     @Override protected void mmdWw (int a, int d) throws M68kException {
  3840:        RP5C15.rtcWriteByte (a + 1, d);
  3841:      }
  3842:     @Override protected void mmdWl (int a, int d) throws M68kException {
  3843:        RP5C15.rtcWriteByte (a + 1, d >> 16);
  3844:        RP5C15.rtcWriteByte (a + 3, d);
  3845:      }
  3846:   },  //MMD_RTC_NEXT
  3847: 
  3848:   //--------------------------------------------------------------------------------
  3849:   //MMD_RTC_TEST RTC
  3850:   MMD_RTC_TEST {
  3851:     @Override public String toString () {
  3852:       return Multilingual.mlnJapanese ? "RTC テスト" : "RTC test";  //Real-Time Clock
  3853:     }
  3854:     //ピーク
  3855:     @Override protected byte mmdPbs (int a) {
  3856:       return (byte) RP5C15.rtcPeekByte (a);
  3857:     }
  3858:     @Override protected int mmdPbz (int a) {
  3859:       return RP5C15.rtcPeekByte (a);
  3860:     }
  3861:     @Override protected int mmdPws (int a) {
  3862:       return RP5C15.rtcPeekByte (a + 1);
  3863:     }
  3864:     @Override protected int mmdPwz (int a) {
  3865:       return RP5C15.rtcPeekByte (a + 1);
  3866:     }
  3867:     @Override protected int mmdPls (int a) {
  3868:       return (RP5C15.rtcPeekByte (a + 1) << 16 |
  3869:               RP5C15.rtcPeekByte (a + 3));
  3870:     }
  3871:     //リード
  3872:     @Override protected byte mmdRbs (int a) throws M68kException {
  3873:        RP5C15.rtcTestUpdate ();
  3874:        return (byte) RP5C15.rtcReadByte (a);
  3875:      }
  3876:     @Override protected int mmdRbz (int a) throws M68kException {
  3877:        RP5C15.rtcTestUpdate ();
  3878:        return RP5C15.rtcReadByte (a);
  3879:      }
  3880:     @Override protected int mmdRws (int a) throws M68kException {
  3881:        RP5C15.rtcTestUpdate ();
  3882:        return RP5C15.rtcReadByte (a + 1);
  3883:      }
  3884:     @Override protected int mmdRwz (int a) throws M68kException {
  3885:        RP5C15.rtcTestUpdate ();
  3886:        return RP5C15.rtcReadByte (a + 1);
  3887:      }
  3888:     @Override protected int mmdRls (int a) throws M68kException {
  3889:        RP5C15.rtcTestUpdate ();
  3890:        return (RP5C15.rtcReadByte (a + 1) << 16 |
  3891:                RP5C15.rtcReadByte (a + 3));
  3892:      }
  3893:     //ライト
  3894:     @Override protected void mmdWb (int a, int d) throws M68kException {
  3895:        RP5C15.rtcTestUpdate ();
  3896:        RP5C15.rtcWriteByte (a, d);
  3897:      }
  3898:     @Override protected void mmdWw (int a, int d) throws M68kException {
  3899:        RP5C15.rtcTestUpdate ();
  3900:        RP5C15.rtcWriteByte (a + 1, d);
  3901:      }
  3902:     @Override protected void mmdWl (int a, int d) throws M68kException {
  3903:        RP5C15.rtcTestUpdate ();
  3904:        RP5C15.rtcWriteByte (a + 1, d >> 16);
  3905:        RP5C15.rtcWriteByte (a + 3, d);
  3906:      }
  3907:   },  //MMD_RTC_TEST
  3908: 
  3909:   //--------------------------------------------------------------------------------
  3910:   //MMD_PRN プリンタポート
  3911:   MMD_PRN {
  3912:     @Override public String toString () {
  3913:       return Multilingual.mlnJapanese ? "プリンタポート" : "Printer Port";
  3914:     }
  3915:     //リード
  3916:     @Override protected int mmdRbz (int a) throws M68kException {
  3917:        a &= XEiJ.BUS_MOTHER_MASK;
  3918:        return (a == PrinterPort.PRN_DATA ? PrinterPort.prnReadData () :
  3919:                a == PrinterPort.PRN_STROBE ? PrinterPort.prnReadStrobe () :
  3920:                0);
  3921:      }
  3922:     @Override protected int mmdRwz (int a) throws M68kException {
  3923:        a &= XEiJ.BUS_MOTHER_MASK;
  3924:        return mmdRbz (a) << 8 | mmdRbz (a + 1);
  3925:      }
  3926:     @Override protected int mmdRls (int a) throws M68kException {
  3927:        a &= XEiJ.BUS_MOTHER_MASK;
  3928:        return mmdRwz (a) << 16 | mmdRwz (a + 2);
  3929:      }
  3930:     //ライト
  3931:     @Override protected void mmdWb (int a, int d) throws M68kException {
  3932:        a &= XEiJ.BUS_MOTHER_MASK;
  3933:        if (a == PrinterPort.PRN_DATA) {
  3934:          PrinterPort.prnWriteData (d);
  3935:        } else if (a == PrinterPort.PRN_STROBE) {
  3936:          PrinterPort.prnWriteStrobe (d);
  3937:        }
  3938:      }
  3939:     @Override protected void mmdWw (int a, int d) throws M68kException {
  3940:        a &= XEiJ.BUS_MOTHER_MASK;
  3941:        mmdWb (a    , d >> 8);
  3942:        mmdWb (a + 1, d     );
  3943:      }
  3944:     @Override protected void mmdWl (int a, int d) throws M68kException {
  3945:        a &= XEiJ.BUS_MOTHER_MASK;
  3946:        mmdWw (a    , d >> 16);
  3947:        mmdWw (a + 2, d      );
  3948:      }
  3949:   },  //MMD_PRN
  3950: 
  3951:   //--------------------------------------------------------------------------------
  3952:   //MMD_SYS システムポート
  3953:   MMD_SYS {
  3954:     @Override public String toString () {
  3955:       return Multilingual.mlnJapanese ? "システムポート" : "System Port";
  3956:     }
  3957:     //リード
  3958:     @Override protected int mmdRbz (int a) throws M68kException {
  3959:        switch (a & 15) {
  3960:        case 0x01:
  3961:          return 0b11110000 | VideoController.vcnTargetContrastPort;
  3962:        case 0x03:
  3963:          return 0b11111000;
  3964:        case 0x07:
  3965:          return 0b11111100 | CRTC.crtHRLPort << 1;
  3966:        case 0x0b:
  3967:          return XEiJ.mpuCoreType == 0 ? XEiJ.mpuClockMHz <= 10.0 ? 0xff : 0xfe : 0xdc;
  3968:        }
  3969:        return 0xff;
  3970:      }
  3971:     @Override protected int mmdRwz (int a) throws M68kException {
  3972:        return mmdRbz (a) << 8 | mmdRbz (a + 1);
  3973:      }
  3974:     @Override protected int mmdRls (int a) throws M68kException {
  3975:        return mmdRwz (a) << 16 | mmdRwz (a + 2);
  3976:      }
  3977:     //ライト
  3978:     @Override protected void mmdWb (int a, int d) throws M68kException {
  3979:        switch (a & 15) {
  3980:        case 0x01:
  3981:          VideoController.vcnTargetContrastPort = d & 15;
  3982:          {
  3983:            int curr = VideoController.vcnTargetContrastMask == 0 ? VideoController.vcnTargetContrastPort : VideoController.vcnTargetContrastTest;
  3984:            if (VideoController.vcnTargetContrastCurr != curr) {
  3985:              VideoController.vcnTargetContrastCurr = curr;
  3986:              VideoController.vcnTargetScaledContrast = VideoController.VCN_CONTRAST_SCALE * VideoController.vcnTargetContrastCurr;
  3987:              CRTC.crtContrastClock = XEiJ.mpuClockTime;
  3988:              CRTC.crtFrameTaskClock = Math.min (CRTC.crtContrastClock, CRTC.crtCaptureClock);
  3989:            }
  3990:          }
  3991:          return;
  3992:        case 0x07:
  3993:          {
  3994:            CRTC.crtHRLPort = d >> 1 & 1;
  3995:            int curr = CRTC.crtHRLMask == 0 ? CRTC.crtHRLPort : CRTC.crtHRLTest;
  3996:            if (CRTC.crtHRLCurr != curr) {
  3997:              CRTC.crtHRLCurr = curr;
  3998:              CRTC.crtRestart ();
  3999:            }
  4000:            if ((d & 1 << 2) != 0) {
  4001:              XEiJ.sysResetNMI ();  //NMIリセット
  4002:            }
  4003:          }
  4004:          return;
  4005:        case 0x0d:
  4006:          XEiJ.smrWriteEnableOn = d == 0x31;
  4007:          return;
  4008:        }
  4009:      }
  4010:     @Override protected void mmdWw (int a, int d) throws M68kException {
  4011:        a &= XEiJ.BUS_MOTHER_MASK;
  4012:        mmdWb (a    , d >> 8);
  4013:        mmdWb (a + 1, d     );
  4014:      }
  4015:     @Override protected void mmdWl (int a, int d) throws M68kException {
  4016:        a &= XEiJ.BUS_MOTHER_MASK;
  4017:        mmdWw (a    , d >> 16);
  4018:        mmdWw (a + 2, d      );
  4019:      }
  4020:   },  //MMD_SYS
  4021: 
  4022:   //--------------------------------------------------------------------------------
  4023:   //MMD_OPM FM音源
  4024:   MMD_OPM {
  4025:     @Override public String toString () {
  4026:       return Multilingual.mlnJapanese ? "FM 音源" : "FM Sound Generator";
  4027:     }
  4028:     //リード
  4029:     @Override protected int mmdRbz (int a) throws M68kException {
  4030:        a &= XEiJ.BUS_MOTHER_MASK;
  4031:        return (a & 0x03) == 3 ? (XEiJ.mpuClockTime < YM2151.opmBusyClock ? 0x80 : 0x00) | YM2151.opmISTB | YM2151.opmISTA : 0xff;
  4032:      }
  4033:     @Override protected int mmdRwz (int a) throws M68kException {
  4034:        a &= XEiJ.BUS_MOTHER_MASK;
  4035:        return mmdRbz (a) << 8 | mmdRbz (a + 1);
  4036:      }
  4037:     @Override protected int mmdRls (int a) throws M68kException {
  4038:        a &= XEiJ.BUS_MOTHER_MASK;
  4039:        return mmdRwz (a) << 16 | mmdRwz (a + 2);
  4040:      }
  4041:     //ライト
  4042:     @Override protected void mmdWb (int a, int d) throws M68kException {
  4043:        a &= XEiJ.BUS_MOTHER_MASK;
  4044:        a &= 3;
  4045:        if (a == 3) {  //データレジスタ
  4046:          //ビジーフラグをセットする
  4047:          //  データレジスタに書き込んでからビジーフラグがセットされるまでのタイムラグを再現することもできなくはないが、
  4048:          //  実機をクロックアップすると動かなくなるソフトが実機と同じように動かなくなるだけのような気がするのでやめておく
  4049:          YM2151.opmBusyClock = XEiJ.mpuClockTime + XEiJ.TMR_FREQ / YM2151.OPM_OSC_FREQ * 68;
  4050:          //除算の負荷を軽減するためYM2151.opmPointerを進める必要があるかどうかを先に確認する
  4051:          if (SoundSource.sndBlockClock - SoundSource.SND_BLOCK_TIME + YM2151.OPM_SAMPLE_TIME / SoundSource.SND_CHANNELS * YM2151.opmPointer < XEiJ.mpuClockTime) {
  4052:            //現在のブロックの残り時間が1サンプルの時間の倍数になるように切り上げる
  4053:            YM2151.opmUpdate (SoundSource.SND_CHANNELS * (YM2151.OPM_BLOCK_SAMPLES - Math.max (0, (int) ((double) (SoundSource.sndBlockClock - XEiJ.mpuClockTime) / (double) YM2151.OPM_SAMPLE_TIME))));
  4054:          }
  4055:          YM2151.opmSetData (YM2151.opmAddress, d);
  4056:        } else if (a == 1) {  //アドレスレジスタ
  4057:          //アドレスレジスタへの書き込みではビジーフラグをセットしない
  4058:          //! 未対応。X68030のときアドレスレジスタへの書き込みに限って約1.2μsのウェイトを追加する
  4059:          //  http://retropc.net/x68000/software/hardware/060turbo/060opmp/060opmp.htm
  4060:          YM2151.opmAddress = 0xff & d;
  4061:        }
  4062:      }
  4063:     @Override protected void mmdWw (int a, int d) throws M68kException {
  4064:        a &= XEiJ.BUS_MOTHER_MASK;
  4065:        mmdWb (a    , d >> 8);
  4066:        mmdWb (a + 1, d     );
  4067:      }
  4068:     @Override protected void mmdWl (int a, int d) throws M68kException {
  4069:        a &= XEiJ.BUS_MOTHER_MASK;
  4070:        mmdWw (a    , d >> 16);
  4071:        mmdWw (a + 2, d      );
  4072:      }
  4073:   },  //MMD_OPM
  4074: 
  4075:   //--------------------------------------------------------------------------------
  4076:   //MMD_PCM ADPCM音源
  4077:   MMD_PCM {
  4078:     @Override public String toString () {
  4079:       return Multilingual.mlnJapanese ? "ADPCM 音源" : "ADPCM Sound Generator";
  4080:     }
  4081:     //リード
  4082:     @Override protected int mmdRbz (int a) throws M68kException {
  4083:        a &= XEiJ.BUS_MOTHER_MASK;
  4084:        return (a & 0x03) == 1 ? (ADPCM.pcmActive ? 0b10000000 : 0) | 0x40 : 0xff;
  4085:      }
  4086:     @Override protected int mmdRwz (int a) throws M68kException {
  4087:        a &= XEiJ.BUS_MOTHER_MASK;
  4088:        return mmdRbz (a) << 8 | mmdRbz (a + 1);
  4089:      }
  4090:     @Override protected int mmdRls (int a) throws M68kException {
  4091:        a &= XEiJ.BUS_MOTHER_MASK;
  4092:        return mmdRwz (a) << 16 | mmdRwz (a + 2);
  4093:      }
  4094:     //ライト
  4095:     @Override protected void mmdWb (int a, int d) throws M68kException {
  4096:        a &= XEiJ.BUS_MOTHER_MASK;
  4097:        a &= 3;
  4098:        if (a == 1) {  //コマンド
  4099:          if ((d & 0b00000001) != 0) {  //動作終了
  4100:            if (ADPCM.pcmActive) {  //動作中
  4101:              ADPCM.pcmClock = XEiJ.FAR_FUTURE;
  4102:              TickerQueue.tkqRemove (SoundSource.sndPcmTicker);
  4103:              ADPCM.pcmActive = false;
  4104:              ADPCM.pcmEncodedData = -1;
  4105:              ADPCM.pcmDecoderPointer = 0;
  4106:              HD63450.dmaRisePCL (3);
  4107:            }
  4108:          } else if ((d & 0b00000010) != 0) {  //動作開始
  4109:            if (!ADPCM.pcmActive) {  //停止中
  4110:              //現在のブロックの残り時間が1サンプルの時間の倍数になるように切り上げる
  4111:              int remainingSamples = Math.max (0, (int) ((double) (SoundSource.sndBlockClock - XEiJ.mpuClockTime) / (double) ADPCM.PCM_SAMPLE_TIME));  //現在のブロックの残りサンプル数
  4112:              ADPCM.pcmClock = SoundSource.sndBlockClock - ADPCM.PCM_SAMPLE_TIME * (long) remainingSamples;  //書き込み開始時刻
  4113:              TickerQueue.tkqAdd (SoundSource.sndPcmTicker, ADPCM.pcmClock);
  4114:              ADPCM.pcmActive = true;
  4115:              int newPointer = SoundSource.SND_CHANNELS * (ADPCM.PCM_BLOCK_SAMPLES - remainingSamples);  //書き込み開始位置
  4116:              if (ADPCM.pcmPointer < newPointer) {
  4117:                ADPCM.pcmFillBuffer (newPointer);
  4118:              } else {
  4119:                ADPCM.pcmPointer = newPointer;  //少し戻る場合がある
  4120:              }
  4121:              //DMAに最初のデータを要求する
  4122:              HD63450.dmaFallPCL (3);
  4123:            }
  4124:            //} else if ((d & 0b00000100) != 0) {  //録音開始
  4125:            //! 非対応
  4126:          }
  4127:        } else if (a == 3) {  //データ
  4128:          if (ADPCM.pcmActive) {
  4129:            ADPCM.pcmEncodedData = d & 255;
  4130:            HD63450.dmaRisePCL (3);
  4131:          }
  4132:        }
  4133:      }
  4134:     @Override protected void mmdWw (int a, int d) throws M68kException {
  4135:        a &= XEiJ.BUS_MOTHER_MASK;
  4136:        mmdWb (a    , d >> 8);
  4137:        mmdWb (a + 1, d     );
  4138:      }
  4139:     @Override protected void mmdWl (int a, int d) throws M68kException {
  4140:        a &= XEiJ.BUS_MOTHER_MASK;
  4141:        mmdWw (a    , d >> 16);
  4142:        mmdWw (a + 2, d      );
  4143:      }
  4144:   },  //MMD_PCM
  4145: 
  4146:   //--------------------------------------------------------------------------------
  4147:   //MMD_FDC FDコントローラ
  4148:   MMD_FDC {
  4149:     @Override public String toString () {
  4150:       return Multilingual.mlnJapanese ? "FD コントローラ" : "FD Controller";
  4151:     }
  4152:     //ピーク
  4153:     @Override protected byte mmdPbs (int a) {
  4154:       return (byte) mmdPbz (a);
  4155:     }
  4156:     @Override protected int mmdPbz (int a) {
  4157:       a &= XEiJ.BUS_MOTHER_MASK & ~1;  //bit0を無視する
  4158:       switch (a) {
  4159:       case FDC.FDC_STATUS_PORT & ~1:  //0x00e94001
  4160:         return FDC.fdcPeekStatus ();
  4161:       case FDC.FDC_DATA_PORT & ~1:  //0x00e94003
  4162:         return FDC.fdcPeekData ();
  4163:       case FDC.FDC_DRIVE_STATUS & ~1:  //0x00e94005
  4164:         return FDC.fdcPeekDriveStatus ();
  4165:       }
  4166:       return 0xff;
  4167:     }
  4168:     @Override protected int mmdPws (int a) {
  4169:       return (short) (mmdPbz (a) << 8 | mmdPbz (a + 1));
  4170:     }
  4171:     @Override protected int mmdPwz (int a) {
  4172:       return mmdPbz (a) << 8 | mmdPbz (a + 1);
  4173:     }
  4174:     @Override protected int mmdPls (int a) {
  4175:       return mmdPwz (a) << 16 | mmdPwz (a + 2);
  4176:     }
  4177:     //リード
  4178:     @Override protected int mmdRbz (int a) throws M68kException {
  4179:        a &= XEiJ.BUS_MOTHER_MASK & ~1;  //bit0を無視する
  4180:        switch (a) {
  4181:        case FDC.FDC_STATUS_PORT & ~1:  //0x00e94001
  4182:          return FDC.fdcReadStatus ();
  4183:        case FDC.FDC_DATA_PORT & ~1:  //0x00e94003
  4184:          return FDC.fdcReadData ();
  4185:        case FDC.FDC_DRIVE_STATUS & ~1:  //0x00e94005
  4186:          return FDC.fdcReadDriveStatus ();
  4187:        }
  4188:        return 0xff;
  4189:      }
  4190:     @Override protected int mmdRwz (int a) throws M68kException {
  4191:        return mmdRbz (a) << 8 | mmdRbz (a + 1);
  4192:      }
  4193:     @Override protected int mmdRls (int a) throws M68kException {
  4194:        return mmdRwz (a) << 16 | mmdRwz (a + 2);
  4195:      }
  4196:     //ライト
  4197:     @Override protected void mmdWb (int a, int d) throws M68kException {
  4198:        a &= XEiJ.BUS_MOTHER_MASK & ~1;  //bit0を無視する
  4199:        switch (a) {
  4200:        case FDC.FDC_STATUS_PORT & ~1:  //0x00e94001
  4201:          FDC.fdcWriteCommand (d);
  4202:          break;
  4203:        case FDC.FDC_DATA_PORT & ~1:  //0x00e94003
  4204:          FDC.fdcWriteData (d);
  4205:          break;
  4206:        case FDC.FDC_DRIVE_STATUS & ~1:  //0x00e94005
  4207:          FDC.fdcWriteDriveControl (d);
  4208:          break;
  4209:        case FDC.FDC_DRIVE_SELECT & ~1:  //0x00e94007
  4210:          FDC.fdcWriteDriveSelect (d);
  4211:          break;
  4212:        }
  4213:      }
  4214:     @Override protected void mmdWw (int a, int d) throws M68kException {
  4215:        mmdWb (a    , d >> 8);
  4216:        mmdWb (a + 1, d     );
  4217:      }
  4218:     @Override protected void mmdWl (int a, int d) throws M68kException {
  4219:        mmdWw (a    , d >> 16);
  4220:        mmdWw (a + 2, d      );
  4221:      }
  4222:   },  //MMD_FDC
  4223: 
  4224:   //--------------------------------------------------------------------------------
  4225:   //MMD_HDC SASI HDコントローラ
  4226:   MMD_HDC {
  4227:     @Override public String toString () {
  4228:       return Multilingual.mlnJapanese ? "内蔵 SASI/SCSI ポート" : "Internal SASI/SCSI Port";  //SCSIのIはInterfaceなのだからSCSIインタフェイスはおかしい
  4229:     }
  4230:     //ピーク
  4231:     @Override protected byte mmdPbs (int a) {
  4232:       a &= XEiJ.BUS_MOTHER_MASK;
  4233:       //内蔵SCSIを持つ機種でもSASIポートがないと起動できない
  4234:       switch (a) {
  4235:       case HDC.HDC_DATA_PORT:  //0x00e96001
  4236:         return (byte) HDC.hdcPeekData ();
  4237:       case HDC.HDC_STATUS_PORT:  //0x00e96003
  4238:         return (byte) HDC.hdcPeekStatus ();
  4239:       case HDC.HDC_RESET_PORT:  //0x00e96005
  4240:         return 0;
  4241:       case HDC.HDC_SELECTION_PORT:  //0x00e96007
  4242:         return 0;
  4243:       }
  4244:       if (SPC.spcSCSIINOn) {
  4245:         if ((a & -32) == SPC.SPC_BASE_IN) {
  4246:           return (byte) SPC.spcSCSIINChip.spiPeek (a);
  4247:         }
  4248:       }
  4249:       return 0;
  4250:     }
  4251:     @Override protected int mmdPbz (int a) {
  4252:       a &= XEiJ.BUS_MOTHER_MASK;
  4253:       //内蔵SCSIを持つ機種でもSASIポートがないと起動できない
  4254:       switch (a) {
  4255:       case HDC.HDC_DATA_PORT:  //0x00e96001
  4256:         return HDC.hdcPeekData ();
  4257:       case HDC.HDC_STATUS_PORT:  //0x00e96003
  4258:         return HDC.hdcPeekStatus ();
  4259:       case HDC.HDC_RESET_PORT:  //0x00e96005
  4260:         return 0;
  4261:       case HDC.HDC_SELECTION_PORT:  //0x00e96007
  4262:         return 0;
  4263:       }
  4264:       if (SPC.spcSCSIINOn) {
  4265:         if ((a & -32) == SPC.SPC_BASE_IN) {
  4266:           return SPC.spcSCSIINChip.spiPeek (a);
  4267:         }
  4268:       }
  4269:       return 0;
  4270:     }
  4271:     @Override protected int mmdPws (int a) {
  4272:       a &= XEiJ.BUS_MOTHER_MASK;
  4273:       return (short) (mmdPbz (a) << 8 | mmdPbz (a + 1));
  4274:     }
  4275:     @Override protected int mmdPwz (int a) {
  4276:       a &= XEiJ.BUS_MOTHER_MASK;
  4277:       return mmdPbz (a) << 8 | mmdPbz (a + 1);
  4278:     }
  4279:     @Override protected int mmdPls (int a) {
  4280:       a &= XEiJ.BUS_MOTHER_MASK;
  4281:       return mmdPwz (a) << 16 | mmdPwz (a + 2);
  4282:     }
  4283:     //リード
  4284:     @Override protected byte mmdRbs (int a) throws M68kException {
  4285:        a &= XEiJ.BUS_MOTHER_MASK;
  4286:        //内蔵SCSIを持つ機種でもSASIポートがないと起動できない
  4287:        switch (a) {
  4288:        case HDC.HDC_DATA_PORT:  //0x00e96001
  4289:          return (byte) HDC.hdcReadData ();
  4290:        case HDC.HDC_STATUS_PORT:  //0x00e96003
  4291:          return (byte) HDC.hdcReadStatus ();
  4292:        case HDC.HDC_RESET_PORT:  //0x00e96005
  4293:          return 0;
  4294:        case HDC.HDC_SELECTION_PORT:  //0x00e96007
  4295:          return 0;
  4296:        }
  4297:        if (SPC.spcSCSIINOn) {
  4298:          if ((a & -32) == SPC.SPC_BASE_IN) {
  4299:            return (byte) SPC.spcSCSIINChip.spiRead (a);
  4300:          }
  4301:        }
  4302:        return super.mmdRbs (a);  //バスエラー
  4303:      }
  4304:     @Override protected int mmdRbz (int a) throws M68kException {
  4305:        a &= XEiJ.BUS_MOTHER_MASK;
  4306:        //内蔵SCSIを持つ機種でもSASIポートがないと起動できない
  4307:        switch (a) {
  4308:        case HDC.HDC_DATA_PORT:  //0x00e96001
  4309:          return HDC.hdcReadData ();
  4310:        case HDC.HDC_STATUS_PORT:  //0x00e96003
  4311:          return HDC.hdcReadStatus ();
  4312:        case HDC.HDC_RESET_PORT:  //0x00e96005
  4313:          return 0;
  4314:        case HDC.HDC_SELECTION_PORT:  //0x00e96007
  4315:          return 0;
  4316:        }
  4317:        if (SPC.spcSCSIINOn) {
  4318:          if ((a & -32) == SPC.SPC_BASE_IN) {
  4319:            return SPC.spcSCSIINChip.spiRead (a);
  4320:          }
  4321:        }
  4322:        return super.mmdRbz (a);  //バスエラー
  4323:      }
  4324:     @Override protected int mmdRwz (int a) throws M68kException {
  4325:        a &= XEiJ.BUS_MOTHER_MASK;
  4326:        return mmdRbz (a) << 8 | mmdRbz (a + 1);
  4327:      }
  4328:     @Override protected int mmdRls (int a) throws M68kException {
  4329:        a &= XEiJ.BUS_MOTHER_MASK;
  4330:        return mmdRwz (a) << 16 | mmdRwz (a + 2);
  4331:      }
  4332:     //ライト
  4333:     @Override protected void mmdWb (int a, int d) throws M68kException {
  4334:        a &= XEiJ.BUS_MOTHER_MASK;
  4335:        //内蔵SCSIを持つ機種でもSASIポートがないと起動できない
  4336:        switch (a) {
  4337:        case HDC.HDC_DATA_PORT:  //0x00e96001
  4338:          HDC.hdcWriteData (d);
  4339:          return;
  4340:        case HDC.HDC_STATUS_PORT:  //0x00e96003
  4341:          HDC.hdcWriteCommand (d);
  4342:          return;
  4343:        case HDC.HDC_RESET_PORT:  //0x00e96005
  4344:          HDC.hdcWriteReset (d);
  4345:          return;
  4346:        case HDC.HDC_SELECTION_PORT:  //0x00e96007
  4347:          HDC.hdcWriteSelect (d);
  4348:          return;
  4349:        }
  4350:        if (SPC.spcSCSIINOn) {
  4351:          if ((a & -32) == SPC.SPC_BASE_IN) {
  4352:            SPC.spcSCSIINChip.spiWrite (a, d);
  4353:            return;
  4354:          }
  4355:        }
  4356:        super.mmdWb (a, d);  //バスエラー
  4357:      }
  4358:     @Override protected void mmdWw (int a, int d) throws M68kException {
  4359:        a &= XEiJ.BUS_MOTHER_MASK;
  4360:        mmdWb (a    , d >> 8);
  4361:        mmdWb (a + 1, d     );
  4362:      }
  4363:     @Override protected void mmdWl (int a, int d) throws M68kException {
  4364:        a &= XEiJ.BUS_MOTHER_MASK;
  4365:        mmdWw (a    , d >> 16);
  4366:        mmdWw (a + 2, d      );
  4367:      }
  4368:   },  //MMD_HDC
  4369: 
  4370:   //--------------------------------------------------------------------------------
  4371:   //MMD_SCC SCC
  4372:   //  アドレスは下位3bitだけデコードされる。0x00e98008以降は0x00e98000~0x00e98007の繰り返し
  4373:   //  偶数アドレスをバイトサイズでアクセスするとバスエラーになる
  4374:   //  ワードリードはバスエラーにならず0xffxxが返る
  4375:   //  ロングリードは0xffxxffxxが返る
  4376:   MMD_SCC {
  4377:     @Override public String toString () {
  4378:       return Multilingual.mlnJapanese ? "SCC" : "SCC";  //Serial Communication Controller
  4379:     }
  4380:     //ピーク
  4381:     @Override protected byte mmdPbs (int a) {
  4382:       try {
  4383:         //! 未対応
  4384:         return mmdRbs (a);
  4385:       } catch (M68kException e) {
  4386:       }
  4387:       return -1;
  4388:     }
  4389:     @Override protected int mmdPbz (int a) {
  4390:       try {
  4391:         //! 未対応
  4392:         return mmdRbz (a);
  4393:       } catch (M68kException e) {
  4394:       }
  4395:       return 255;
  4396:     }
  4397:     @Override protected int mmdPws (int a) {
  4398:       return 0xffffff00 | mmdPbz (a + 1);
  4399:     }
  4400:     @Override protected int mmdPwz (int a) {
  4401:       return 0xff00 | mmdPbz (a + 1);
  4402:     }
  4403:     @Override protected int mmdPls (int a) {
  4404:       return 0xff00ff00 | mmdPbz (a + 1) << 16 | mmdPbz (a + 3);
  4405:     }
  4406:     //リード
  4407:     @Override protected int mmdRbz (int a) throws M68kException {
  4408:        int d = 0;
  4409:        switch (a & 7) {
  4410:          //------------------------------------------------
  4411:        case Z8530.SCC_0_COMMAND & 7:  //ポートBコマンド読み出し
  4412:          switch (Z8530.scc0RegisterNumber) {
  4413:          case 0:  //RR0
  4414:            //  0x80  ブレークまたはアボート
  4415:            //  0x40  送信アンダーラン
  4416:            //  0x20  CTS(0=送信禁止,1=送信許可)
  4417:            //  0x10  SYNC
  4418:            //  0x08  DCD
  4419:            //  0x04  送信バッファ空
  4420:            //  0x02  ボーレートカウント0
  4421:            //  0x01  受信バッファフル
  4422:            d = Z8530.scc0InputCounter < 3 ? 0x25 : 0x24;
  4423:            break;
  4424:          case 2:  //RR2
  4425:            //修飾割り込みベクタ
  4426:            //  ポートBのRR2はWR2に設定したベクタを割り込み要求で加工して返す
  4427:            d = (Z8530.scc1aReceiveRequest != 0 ? Z8530.scc1aReceiveVector :  //1A受信バッファフル(RS-232C受信)
  4428:                 Z8530.scc1aSendRequest != 0 ? Z8530.scc1aSendVector :  //1A送信バッファ空(RS-232C送信)
  4429:                 Z8530.scc0bReceiveRequest != 0 ? Z8530.scc0bReceiveVector :  //0B受信バッファフル(マウス受信)
  4430:                 Z8530.sccInterruptVector);
  4431:            break;
  4432:          case 3:  //RR3
  4433:            //ポートBのRR3は常に0
  4434:            //  ポートBの割り込みペンディングを見るときはポートAのRR3を参照する
  4435:            //d = 0;
  4436:            break;
  4437:          case 12:  //RR12
  4438:            d = Z8530.scc0BaudRateGen & 255;
  4439:            break;
  4440:          case 13:  //RR13
  4441:            d = Z8530.scc0BaudRateGen >> 8 & 255;
  4442:            break;
  4443:          default:
  4444:            if (Z8530.SCC_DEBUG_TRACE) {
  4445:              System.out.println ("unimplemented register");
  4446:            }
  4447:          }
  4448:          Z8530.scc0RegisterNumber = 0;
  4449:          break;
  4450:          //------------------------------------------------
  4451:        case Z8530.SCC_0_DATA & 7:  //ポートBデータ読み出し(マウス受信)
  4452:          if (Z8530.scc0InputCounter == 0) {  //1バイト目
  4453:            d = XEiJ.musDataRight | XEiJ.musDataLeft;
  4454:            if (!XEiJ.musOnScreen) {  //ホストのマウスカーソルがスクリーン上にない
  4455:              //XEiJ.musShow ();
  4456:              if (XEiJ.musCursorNumber != 1 && XEiJ.musCursorAvailable) {
  4457:                XEiJ.musCursorNumber = 1;
  4458:                XEiJ.pnlPanel.setCursor (XEiJ.musCursorArray[1]);  //ホストのマウスカーソルを表示する
  4459:              }
  4460:              Z8530.scc0Data1 = Z8530.scc0Data2 = 0;
  4461:            } else if (XEiJ.musSeamlessOn) {  //シームレス
  4462:              int on, dx, dy, coeff = 256;
  4463:              if (XEiJ.mpuCoreType < 6) {  //MMUなし
  4464:                if (Z8530.SCC_FSX_MOUSE &&
  4465:                    Z8530.sccFSXMouseHook != 0 &&  //FSX.Xが常駐している
  4466:                    MainMemory.mmrRls (0x0938) == Z8530.sccFSXMouseHook) {  //マウス受信データ処理ルーチンがFSX.Xを指している。SX-Windowが動作中
  4467:                  on = MainMemory.mmrRws (Z8530.sccFSXMouseWork + 0x2e) == 0 ? 1 : 0;  //SX-Windowのマウスカーソルの表示状態。Obscureのときは表示されているとみなす
  4468:                  int xy = MainMemory.mmrRls (Z8530.sccFSXMouseWork + 0x0a);
  4469:                  dx = (xy >> 16) - CRTC.crtR10TxXPort;  //SX-Windowのマウスカーソルの見かけのX座標
  4470:                  dy = (short) xy - CRTC.crtR11TxYPort;  //SX-Windowのマウスカーソルの見かけのY座標
  4471:                  coeff = MainMemory.mmrRwz (Z8530.sccFSXMouseWork + 0x04);  //ポインタの移動量。係数*256
  4472:                } else {  //SX-Windowが動作中ではない
  4473:                  on = MainMemory.mmrRbs (0x0aa2);  //IOCSのマウスカーソルの表示状態
  4474:                  int xy = MainMemory.mmrRls (0x0ace);
  4475:                  dx = xy >> 16;  //IOCSのマウスカーソルのX座標
  4476:                  dy = (short) xy;  //IOCSのマウスカーソルのY座標
  4477:                }
  4478:              } else {  //MMUあり
  4479:                if (Z8530.SCC_FSX_MOUSE &&
  4480:                    Z8530.sccFSXMouseHook != 0 &&  //FSX.Xが常駐している
  4481:                    MC68060.mmuPeekLongData (0x0938, 1) == Z8530.sccFSXMouseHook) {  //マウス受信データ処理ルーチンがFSX.Xを指している。SX-Windowが動作中
  4482:                  on = MC68060.mmuPeekWordSignData (Z8530.sccFSXMouseWork + 0x2e, 1) == 0 ? 1 : 0;  //SX-Windowのマウスカーソルの表示状態。Obscureのときは表示されているとみなす
  4483:                  int xy = MC68060.mmuPeekLongData (Z8530.sccFSXMouseWork + 0x0a, 1);
  4484:                  dx = (xy >> 16) - CRTC.crtR10TxXPort;  //SX-Windowのマウスカーソルの見かけのX座標
  4485:                  dy = (short) xy - CRTC.crtR11TxYPort;  //SX-Windowのマウスカーソルの見かけのY座標
  4486:                  coeff = MC68060.mmuPeekWordZeroData (Z8530.sccFSXMouseWork + 0x04, 1);  //ポインタの移動量。係数*256
  4487:                } else {  //SX-Windowが動作中ではない
  4488:                  on = MC68060.mmuPeekByteSignData (0x0aa2, 1);  //IOCSのマウスカーソルの表示状態
  4489:                  int xy = MC68060.mmuPeekLongData (0x0ace, 1);
  4490:                  dx = xy >> 16;  //IOCSのマウスカーソルのX座標
  4491:                  dy = (short) xy;  //IOCSのマウスカーソルのY座標
  4492:                }
  4493:              }
  4494:              dx = XEiJ.musScreenX - dx;  //X方向の移動量
  4495:              dy = XEiJ.musScreenY - dy;  //Y方向の移動量
  4496:              if (XEiJ.musEdgeAccelerationOn) {  //縁部加速を行う
  4497:                final int range = 10;  //加速領域の幅
  4498:                final int speed = 10;  //移動速度
  4499:                if (XEiJ.musScreenX < range) {
  4500:                  dx = -speed;  //左へ
  4501:                } else if (XEiJ.pnlScreenWidth - range <= XEiJ.musScreenX) {
  4502:                  dx = speed;  //右へ
  4503:                }
  4504:                if (XEiJ.musScreenY < range) {
  4505:                  dy = -speed;  //上へ
  4506:                } else if (XEiJ.pnlScreenHeight - range <= XEiJ.musScreenY) {
  4507:                  dy = speed;  //下へ
  4508:                }
  4509:              }
  4510:              if (on != 0) {  //X68000のマウスカーソルが表示されている
  4511:                //XEiJ.musHide ();
  4512:                if (XEiJ.musCursorNumber != 0 && XEiJ.musCursorAvailable) {
  4513:                  XEiJ.musCursorNumber = 0;
  4514:                  XEiJ.pnlPanel.setCursor (XEiJ.musCursorArray[0]);  //ホストのマウスカーソルを消す
  4515:                }
  4516:              } else {  //X68000のマウスカーソルが表示されていない
  4517:                //XEiJ.musShow ();
  4518:                if (XEiJ.musCursorNumber != 1 && XEiJ.musCursorAvailable) {
  4519:                  XEiJ.musCursorNumber = 1;
  4520:                  XEiJ.pnlPanel.setCursor (XEiJ.musCursorArray[1]);  //ホストのマウスカーソルを表示する
  4521:                }
  4522:              }
  4523:              if (coeff != 256 && coeff != 0) {
  4524:                //SX-Windowのポインタの移動量の補正
  4525:                dx = (dx << 8) / coeff;
  4526:                dy = (dy << 8) / coeff;
  4527:              }
  4528:              //  XEiJ.MUS_DEACCELERATION_TABLEの値が127を越えることはないのでシームレスでオーバーフローフラグがセットされることはない
  4529:              //  rbzで返すので負数のときのゼロ拡張を忘れないこと
  4530:              Z8530.scc0Data1 = (dx == 0 ? 0 : dx >= 0 ?
  4531:                           XEiJ.MUS_DEACCELERATION_TABLE[Math.min (1024, dx)] :
  4532:                           -XEiJ.MUS_DEACCELERATION_TABLE[Math.min (1024, -dx)] & 255);
  4533:              Z8530.scc0Data2 = (dy == 0 ? 0 : dy >= 0 ?
  4534:                           XEiJ.MUS_DEACCELERATION_TABLE[Math.min (1024, dy)] :
  4535:                           -XEiJ.MUS_DEACCELERATION_TABLE[Math.min (1024, -dy)] & 255);
  4536:            } else {  //エクスクルーシブ
  4537:              //XEiJ.musHide ();
  4538:              if (XEiJ.musCursorNumber != 0 && XEiJ.musCursorAvailable) {
  4539:                XEiJ.musCursorNumber = 0;
  4540:                XEiJ.pnlPanel.setCursor (XEiJ.musCursorArray[0]);  //ホストのマウスカーソルを消す
  4541:              }
  4542:              int ox = XEiJ.pnlScreenX + (XEiJ.pnlZoomWidth >> 1);  //画面の中央
  4543:              int oy = XEiJ.pnlScreenY + (XEiJ.pnlZoomHeight >> 1);
  4544:              XEiJ.rbtRobot.mouseMove (XEiJ.pnlGlobalX + ox, XEiJ.pnlGlobalY + oy);  //マウスカーソルを画面の中央に戻す
  4545:              int dx = XEiJ.musPanelX - ox;
  4546:              int dy = XEiJ.musPanelY - oy;
  4547:              if (XEiJ.musExclusiveStart) {  //エクスクルーシブに切り替えた直後
  4548:                //エクスクルーシブに切り替えた直後の1回だけ相対位置を無視する
  4549:                //  エクスクルーシブに切り替える直前にマウスカーソルが画面の中央から離れていると切り替えた瞬間に画面の端に飛んでしまう
  4550:                dx = 0;
  4551:                dy = 0;
  4552:                XEiJ.musExclusiveStart = false;
  4553:              }
  4554:              //  上下左右のレスポンスが非対称になると気持ち悪いので冗長に書く
  4555:              //  rbzで返すので負数のときのゼロ拡張を忘れないこと
  4556:              if (dx != 0) {
  4557:                if (dx >= 0) {
  4558:                  //dx = dx * Z8530.scc0RatioX + 32768 >> 16;
  4559:                  dx = dx * Z8530.scc0RatioX >> 16;
  4560:                  if (dx > 127) {
  4561:                    d |= 0x10;
  4562:                    dx = 127;
  4563:                  }
  4564:                } else {
  4565:                  //dx = -(-dx * Z8530.scc0RatioX + 32768 >> 16);
  4566:                  dx = -(-dx * Z8530.scc0RatioX >> 16);
  4567:                  if (dx < -128) {
  4568:                    d |= 0x20;
  4569:                    dx = -128;
  4570:                  }
  4571:                  dx &= 255;
  4572:                }
  4573:              }
  4574:              if (dy != 0) {
  4575:                if (dy >= 0) {
  4576:                  //dy = dy * Z8530.scc0RatioY + 32768 >> 16;
  4577:                  dy = dy * Z8530.scc0RatioY >> 16;
  4578:                  if (dy > 127) {
  4579:                    d |= 0x40;
  4580:                    dy = 127;
  4581:                  }
  4582:                } else {
  4583:                  //dy = -(-dy * Z8530.scc0RatioY + 32768 >> 16);
  4584:                  dy = -(-dy * Z8530.scc0RatioY >> 16);
  4585:                  if (dy < -128) {
  4586:                    d |= 0x80;
  4587:                    dy = -128;
  4588:                  }
  4589:                  dy &= 255;
  4590:                }
  4591:              }
  4592:              Z8530.scc0Data1 = dx;
  4593:              Z8530.scc0Data2 = dy;
  4594:            }  //if シームレス else エクスクルーシブ
  4595:            Z8530.scc0InputCounter = 1;
  4596:            //d = d;
  4597:          } else if (Z8530.scc0InputCounter == 1) {  //2バイト目
  4598:            Z8530.scc0InputCounter = 2;
  4599:            d = Z8530.scc0Data1;
  4600:          } else if (Z8530.scc0InputCounter == 2) {  //3バイト目
  4601:            Z8530.scc0InputCounter = 3;
  4602:            d = Z8530.scc0Data2;
  4603:          }
  4604:          break;
  4605:          //------------------------------------------------
  4606:        case Z8530.SCC_1_COMMAND & 7:  //ポートAコマンド読み出し
  4607:          switch (Z8530.scc1RegisterNumber) {
  4608:          case 0:  //RR0
  4609:            //  0x80  ブレークまたはアボート
  4610:            //  0x40  送信アンダーラン
  4611:            //  0x20  CTS(0=送信禁止,1=送信許可)
  4612:            //  0x10  SYNC
  4613:            //  0x08  DCD
  4614:            //  0x04  送信バッファ空
  4615:            //  0x02  ボーレートカウント0
  4616:            //  0x01  受信バッファフル
  4617:            d = Z8530.scc1InputRead != Z8530.scc1InputWrite && Z8530.scc1InputClock <= XEiJ.mpuClockTime ? 0x25 : 0x24;
  4618:            break;
  4619:          case 2:  //RR2
  4620:            //非修飾割り込みベクタ
  4621:            //  ポートAのRR2はWR2に設定したベクタをそのまま返す
  4622:            d = Z8530.sccInterruptVector;
  4623:            break;
  4624:          case 3:  //RR3
  4625:            //割り込みペンディング
  4626:            //  RR3リクエストからインサービスまでの間セットされている
  4627:            //  許可されていない割り込みのビットはセットされない
  4628:            d = Z8530.scc1aReceiveRR3 | Z8530.scc1aSendRR3 | Z8530.scc0bReceiveRR3;
  4629:            break;
  4630:          case 12:  //RR12
  4631:            d = Z8530.scc1BaudRateGen & 255;
  4632:            break;
  4633:          case 13:  //RR13
  4634:            d = Z8530.scc1BaudRateGen >> 8 & 255;
  4635:            break;
  4636:          default:
  4637:            if (Z8530.SCC_DEBUG_TRACE) {
  4638:              System.out.println ("unimplemented register");
  4639:            }
  4640:          }
  4641:          Z8530.scc1RegisterNumber = 0;
  4642:          break;
  4643:          //------------------------------------------------
  4644:        case Z8530.SCC_1_DATA & 7:  //ポートAデータ読み出し(RS-232C受信)
  4645:          if (Z8530.scc1InputRead != Z8530.scc1InputWrite && Z8530.scc1InputClock <= XEiJ.mpuClockTime) {  //受信バッファが空ではなく、受信予定時刻になっているとき
  4646:            d = Z8530.scc1InputBuffer[Z8530.scc1InputRead];  //ゼロ拡張済み
  4647:            Z8530.scc1InputRead = Z8530.scc1InputRead + 1 & Z8530.SCC_1_INPUT_MASK;
  4648:            if (Z8530.scc1InputRead != Z8530.scc1InputWrite) {  //受信バッファが空にならなかったとき
  4649:              Z8530.scc1InputClock += Z8530.scc1Interval;  //受信バッファの先頭のデータの受信予定時刻
  4650:              TickerQueue.tkqAdd (Z8530.sccTicker, Z8530.scc1InputClock);  //割り込みを発生させる
  4651:            } else {  //受信バッファが空になったとき
  4652:              Z8530.scc1InputClock = XEiJ.FAR_FUTURE;
  4653:              TickerQueue.tkqRemove (Z8530.sccTicker);
  4654:            }
  4655:          }
  4656:          break;
  4657:          //------------------------------------------------
  4658:        default:
  4659:          return super.mmdRbz (a);  //バスエラー
  4660:        }
  4661:        if (Z8530.SCC_DEBUG_TRACE && Z8530.sccTraceOn) {
  4662:          System.out.printf ("%08x Z8530.sccRead(0x%08x)=0x%02x\n", XEiJ.regPC0, a, d);
  4663:        }
  4664:        return d;
  4665:      }
  4666:     @Override protected int mmdRws (int a) throws M68kException {
  4667:        return 0xffffff00 | mmdRbz (a + 1);
  4668:      }
  4669:     @Override protected int mmdRwz (int a) throws M68kException {
  4670:        return 0xff00 | mmdRbz (a + 1);
  4671:      }
  4672:     @Override protected int mmdRls (int a) throws M68kException {
  4673:        return 0xff00ff00 | mmdRbz (a + 1) << 16 | mmdRbz (a + 3);
  4674:      }
  4675:     //ライト
  4676:     @Override protected void mmdWb (int a, int d) throws M68kException {
  4677:        d &= 0xff;
  4678:        if (Z8530.SCC_DEBUG_TRACE && Z8530.sccTraceOn) {
  4679:          System.out.printf ("%08x Z8530.sccWrite(0x%08x,0x%02x)\n", XEiJ.regPC0, a, d);
  4680:        }
  4681:        switch (a & 7) {
  4682:          //------------------------------------------------
  4683:        case Z8530.SCC_0_COMMAND & 7:  //ポートBコマンド書き込み
  4684:          switch (Z8530.scc0RegisterNumber) {
  4685:          case 0:  //WR0
  4686:            if ((d & 0xf0) == 0) {  //レジスタ選択
  4687:              Z8530.scc0RegisterNumber = d;
  4688:            } else if (d == 0x38) {  //IUSリセット。割り込み処理が終了し、次の割り込みを受け付ける
  4689:              if (Z8530.scc0bReceiveRR3 != 0) {
  4690:                Z8530.scc0bReceiveRR3 = 0;
  4691:                if (Z8530.scc0InputCounter < 3) {  //3バイト受信するまで割り込み要求を続ける
  4692:                  if (Z8530.scc0bReceiveMask != 0) {
  4693:                    Z8530.scc0bReceiveRR3 = Z8530.SCC_0B_RECEIVE_MASK;
  4694:                    Z8530.scc0bReceiveRequest = Z8530.SCC_0B_RECEIVE_MASK;
  4695:                    XEiJ.mpuIRR |= XEiJ.MPU_SCC_INTERRUPT_MASK;
  4696:                  }
  4697:                }
  4698:              }
  4699:            } else if (d == 0x10) {  //ステータス割り込みリセット
  4700:            } else if (d == 0x30) {  //エラーリセット
  4701:            } else if (d == 0x80) {  //送信CRCジェネレータリセット
  4702:            } else {
  4703:              if (Z8530.SCC_DEBUG_TRACE) {
  4704:                System.out.println ("unimplemented command");
  4705:              }
  4706:            }
  4707:            return;
  4708:          case 1:  //WR1
  4709:            Z8530.scc0bReceiveMask = (d & 0x18) != 0 ? Z8530.SCC_0B_RECEIVE_MASK : 0;
  4710:            if ((d & 0xec) != 0x00) {
  4711:              if (Z8530.SCC_DEBUG_TRACE) {
  4712:                System.out.println ("unimplemented interrupt mode");
  4713:              }
  4714:            }
  4715:            break;
  4716:          case 2:  //WR2
  4717:            Z8530.sccInterruptVector = d;  //割り込みベクタ
  4718:            if (Z8530.SCC_DEBUG_TRACE) {
  4719:              System.out.printf ("Z8530.sccInterruptVector=0x%02x\n", Z8530.sccInterruptVector);
  4720:            }
  4721:            Z8530.sccUpdateVector ();
  4722:            break;
  4723:          case 3:  //WR3
  4724:            if (d == 0xc0) {  //受信禁止
  4725:            } else if (d == 0xc1) {  //受信許可
  4726:            } else {
  4727:              if (Z8530.SCC_DEBUG_TRACE) {
  4728:                System.out.println ("unimplemented receiver configuration");
  4729:              }
  4730:            }
  4731:            break;
  4732:          case 4:  //WR4
  4733:            break;
  4734:          case 5:  //WR5
  4735:            //  0x80  DTR
  4736:            //  0x60  ビット長(0x00=5bit,0x20=7bit,0x40=6bit,0x60=8bit)
  4737:            //  0x10  ブレーク
  4738:            //  0x08  送信許可
  4739:            //  0x04  CRC-16
  4740:            //  0x02  RTS
  4741:            //  0x01  送信CRC
  4742:            {
  4743:              int rts = d >> 1 & 1;
  4744:              if ((~Z8530.scc0Rts & rts) != 0) {  //RTS=0→1。MSCTRL=H→Lとなってマウスに送信要求が出される
  4745:                Z8530.scc0InputCounter = 0;
  4746:                //マウスデータ受信開始
  4747:                if (Z8530.scc0bReceiveMask != 0) {
  4748:                  Z8530.scc0bReceiveRR3 = Z8530.SCC_0B_RECEIVE_MASK;
  4749:                  Z8530.scc0bReceiveRequest = Z8530.SCC_0B_RECEIVE_MASK;
  4750:                  XEiJ.mpuIRR |= XEiJ.MPU_SCC_INTERRUPT_MASK;
  4751:                }
  4752:              }
  4753:              Z8530.scc0Rts = rts;
  4754:              if ((d & 0x75) == 0x60) {
  4755:              } else {
  4756:                if (Z8530.SCC_DEBUG_TRACE) {
  4757:                  System.out.println ("unimplemented sender configuration");
  4758:                }
  4759:              }
  4760:            }
  4761:            break;
  4762:          case 6:  //WR6
  4763:            break;
  4764:          case 7:  //WR7
  4765:            break;
  4766:          case 9:  //WR9
  4767:            if ((d & 0xc0) == 0x40) {  //ポートBリセット
  4768:              Z8530.scc0Rts = 0;
  4769:            } else if ((d & 0xc0) == 0x80) {  //ポートAリセット
  4770:            } else if ((d & 0xc0) == 0xc0) {  //ハードウェアリセット
  4771:              Z8530.scc0Rts = 0;
  4772:            }
  4773:            Z8530.sccVectorInclude = d & 0x11;
  4774:            if (Z8530.SCC_DEBUG_TRACE) {
  4775:              System.out.printf ("Z8530.sccVectorInclude=0x%02x\n", Z8530.sccVectorInclude);
  4776:            }
  4777:            Z8530.sccUpdateVector ();
  4778:            if ((d & 0x26) != 0x00) {
  4779:              if (Z8530.SCC_DEBUG_TRACE) {
  4780:                System.out.println ("unimplemented interrupt configuration");
  4781:              }
  4782:            }
  4783:            break;
  4784:          case 10:  //WR10
  4785:            if (d == 0x00) {
  4786:            } else {
  4787:              if (Z8530.SCC_DEBUG_TRACE) {
  4788:                System.out.println ("unimplemented SDLC configuration");
  4789:              }
  4790:            }
  4791:            break;
  4792:          case 11:  //WR11
  4793:            if (d == 0x50) {  //TRxCは入力
  4794:            } else if (d == 0x56) {  //TRxCからボーレートジェネレータを出力
  4795:            } else {
  4796:              if (Z8530.SCC_DEBUG_TRACE) {
  4797:                System.out.println ("unimplemented clock control");
  4798:              }
  4799:            }
  4800:            break;
  4801:          case 12:  //WR12
  4802:            Z8530.scc0BaudRateGen = Z8530.scc0BaudRateGen & 255 << 8 | d;
  4803:            break;
  4804:          case 13:  //WR13
  4805:            Z8530.scc0BaudRateGen = d << 8 | Z8530.scc0BaudRateGen & 255;
  4806:            break;
  4807:          case 14:  //WR14
  4808:            if (d == 0x02) {  //ボーレートジェネレータ停止
  4809:            } else if (d == 0x03) {  //ボーレートジェネレータ動作
  4810:            } else {
  4811:              if (Z8530.SCC_DEBUG_TRACE) {
  4812:                System.out.println ("unimplemented DPLL configuration");
  4813:              }
  4814:            }
  4815:            break;
  4816:          case 15:  //WR15
  4817:            if (d == 0x00) {
  4818:            } else if (d == 0x80) {
  4819:            } else if (d == 0x88) {
  4820:            } else {
  4821:              if (Z8530.SCC_DEBUG_TRACE) {
  4822:                System.out.println ("unimplemented status interrupt configuration");
  4823:              }
  4824:            }
  4825:            break;
  4826:          default:
  4827:            if (Z8530.SCC_DEBUG_TRACE) {
  4828:              System.out.println ("unimplemented register");
  4829:            }
  4830:          }
  4831:          Z8530.scc0RegisterNumber = 0;
  4832:          return;
  4833:          //------------------------------------------------
  4834:        case Z8530.SCC_0_DATA & 7:  //ポートBデータ書き込み(マウス送信)
  4835:          return;
  4836:          //------------------------------------------------
  4837:        case Z8530.SCC_1_COMMAND & 7:  //ポートAコマンド書き込み
  4838:          switch (Z8530.scc1RegisterNumber) {
  4839:          case 0:  //WR0
  4840:            if ((d & 0xf0) == 0) {  //レジスタ選択
  4841:              Z8530.scc1RegisterNumber = d;
  4842:            } else if (d == 0x38) {  //IUSリセット。割り込み処理が終了し、次の割り込みを受け付ける
  4843:              if (Z8530.scc1aReceiveRR3 != 0) {
  4844:                Z8530.scc1aReceiveRR3 = 0;
  4845:                if (Z8530.scc1InputRead != Z8530.scc1InputWrite) {  //バッファが空になるまで割り込み要求を続ける
  4846:                  TickerQueue.tkqAdd (Z8530.sccTicker, Z8530.scc1InputClock);  //受信バッファの先頭のデータの受信予定時刻
  4847:                }
  4848:              }
  4849:            } else if (d == 0x10) {  //ステータス割り込みリセット
  4850:            } else if (d == 0x30) {  //エラーリセット
  4851:            } else if (d == 0x80) {  //送信CRCジェネレータリセット
  4852:            } else {
  4853:              if (Z8530.SCC_DEBUG_TRACE) {
  4854:                System.out.println ("unimplemented command");
  4855:              }
  4856:            }
  4857:            return;
  4858:          case 1:  //WR1
  4859:            Z8530.scc1aReceiveMask = (d & 0x18) != 0 ? Z8530.SCC_1A_RECEIVE_MASK : 0;
  4860:            Z8530.scc1aSendMask = (d & 0x02) != 0 ? Z8530.SCC_1A_SEND_MASK : 0;
  4861:            if ((d & 0xec) != 0x00) {
  4862:              if (Z8530.SCC_DEBUG_TRACE) {
  4863:                System.out.println ("unimplemented interrupt mode");
  4864:              }
  4865:            }
  4866:            break;
  4867:          case 2:  //WR2
  4868:            Z8530.sccInterruptVector = d;  //割り込みベクタ
  4869:            if (Z8530.SCC_DEBUG_TRACE) {
  4870:              System.out.printf ("Z8530.sccInterruptVector=0x%02x\n", Z8530.sccInterruptVector);
  4871:            }
  4872:            Z8530.sccUpdateVector ();
  4873:            break;
  4874:          case 3:  //WR3
  4875:            if (d == 0xc0) {  //受信禁止
  4876:            } else if (d == 0xc1) {  //受信許可
  4877:            } else {
  4878:              if (Z8530.SCC_DEBUG_TRACE) {
  4879:                System.out.println ("unimplemented receiver configuration");
  4880:              }
  4881:            }
  4882:            break;
  4883:          case 4:  //WR4
  4884:            Z8530.scc1ClockModeShift = d >> 6 == 0 ? 0 : (d >> 6) + 3;  //0=2^0,1=2^4,2=2^5,3=2^6
  4885:            Z8530.scc1Interval = XEiJ.TMR_FREQ / ((Z8530.SCC_FREQ / 2 >> Z8530.scc1ClockModeShift) / (Z8530.scc1BaudRateGen + 2));
  4886:            break;
  4887:          case 5:  //WR5
  4888:            //  0x80  DTR
  4889:            //  0x60  ビット長(0x00=5bit,0x20=7bit,0x40=6bit,0x60=8bit)
  4890:            //  0x10  ブレーク
  4891:            //  0x08  送信許可
  4892:            //  0x04  CRC-16
  4893:            //  0x02  RTS
  4894:            //  0x01  送信CRC
  4895:            {
  4896:              if ((d & 0x75) == 0x60) {
  4897:              } else {
  4898:                if (Z8530.SCC_DEBUG_TRACE) {
  4899:                  System.out.println ("unimplemented sender configuration");
  4900:                }
  4901:              }
  4902:            }
  4903:            break;
  4904:          case 6:  //WR6
  4905:            break;
  4906:          case 7:  //WR7
  4907:            break;
  4908:          case 9:  //WR9
  4909:            if ((d & 0xc0) == 0x40) {  //ポートBリセット
  4910:              Z8530.scc0Rts = 0;
  4911:            } else if ((d & 0xc0) == 0x80) {  //ポートAリセット
  4912:            } else if ((d & 0xc0) == 0xc0) {  //ハードウェアリセット
  4913:              Z8530.scc0Rts = 0;
  4914:            }
  4915:            Z8530.sccVectorInclude = d & 0x11;
  4916:            if (Z8530.SCC_DEBUG_TRACE) {
  4917:              System.out.printf ("Z8530.sccVectorInclude=0x%02x\n", Z8530.sccVectorInclude);
  4918:            }
  4919:            Z8530.sccUpdateVector ();
  4920:            if ((d & 0x2e) != 0x08) {
  4921:              if (Z8530.SCC_DEBUG_TRACE) {
  4922:                System.out.println ("unimplemented interrupt configuration");
  4923:              }
  4924:            }
  4925:            break;
  4926:          case 10:  //WR10
  4927:            if (d == 0x00) {
  4928:            } else {
  4929:              if (Z8530.SCC_DEBUG_TRACE) {
  4930:                System.out.println ("unimplemented SDLC configuration");
  4931:              }
  4932:            }
  4933:            break;
  4934:          case 11:  //WR11
  4935:            if (d == 0x50) {  //TRxCは入力
  4936:            } else if (d == 0x56) {  //TRxCからボーレートジェネレータを出力
  4937:            } else {
  4938:              if (Z8530.SCC_DEBUG_TRACE) {
  4939:                System.out.println ("unimplemented clock control");
  4940:              }
  4941:            }
  4942:            break;
  4943:          case 12:  //WR12
  4944:            Z8530.scc1BaudRateGen = Z8530.scc1BaudRateGen & 255 << 8 | d;
  4945:            Z8530.scc1Interval = XEiJ.TMR_FREQ / ((Z8530.SCC_FREQ / 2 >> Z8530.scc1ClockModeShift) / (Z8530.scc1BaudRateGen + 2));
  4946:            break;
  4947:          case 13:  //WR13
  4948:            Z8530.scc1BaudRateGen = d << 8 | Z8530.scc1BaudRateGen & 255;
  4949:            Z8530.scc1Interval = XEiJ.TMR_FREQ / ((Z8530.SCC_FREQ / 2 >> Z8530.scc1ClockModeShift) / (Z8530.scc1BaudRateGen + 2));
  4950:            break;
  4951:          case 14:  //WR14
  4952:            if (d == 0x02) {  //ボーレートジェネレータ停止
  4953:            } else if (d == 0x03) {  //ボーレートジェネレータ動作
  4954:            } else {
  4955:              if (Z8530.SCC_DEBUG_TRACE) {
  4956:                System.out.println ("unimplemented DPLL configuration");
  4957:              }
  4958:            }
  4959:            break;
  4960:          case 15:  //WR15
  4961:            if (d == 0x00) {
  4962:            } else if (d == 0x80) {
  4963:            } else if (d == 0x88) {
  4964:            } else {
  4965:              if (Z8530.SCC_DEBUG_TRACE) {
  4966:                System.out.println ("unimplemented status interrupt configuration");
  4967:              }
  4968:            }
  4969:            break;
  4970:          default:
  4971:            if (Z8530.SCC_DEBUG_TRACE) {
  4972:              System.out.println ("unimplemented register");
  4973:            }
  4974:          }
  4975:          Z8530.scc1RegisterNumber = 0;
  4976:          return;
  4977:          //------------------------------------------------
  4978:        case Z8530.SCC_1_DATA & 7:  //ポートAデータ書き込み(RS-232C送信)
  4979:          RS232CTerminal.trmPrintSJIS (d);
  4980:          return;
  4981:          //------------------------------------------------
  4982:        default:
  4983:          super.mmdWb (a, d);  //バスエラー
  4984:        }
  4985:      }
  4986:     @Override protected void mmdWw (int a, int d) throws M68kException {
  4987:        mmdWb (a + 1, d);
  4988:      }
  4989:     @Override protected void mmdWl (int a, int d) throws M68kException {
  4990:        mmdWb (a + 1, d >> 16);
  4991:        mmdWb (a + 3, d);
  4992:      }
  4993:   },  //MMD_SCC
  4994: 
  4995:   //--------------------------------------------------------------------------------
  4996:   //MMD_PPI PPI
  4997:   MMD_PPI {
  4998:     @Override public String toString () {
  4999:       return Multilingual.mlnJapanese ? "PPI" : "PPI";  //Programmable Peripheral Interface
  5000:     }
  5001:     //リード
  5002:     @Override protected int mmdRbz (int a) throws M68kException {
  5003:        a &= XEiJ.BUS_MOTHER_MASK;
  5004:        switch (a) {
  5005:        case 0x00e9a001:  //PPI PORT-A ジョイスティック1
  5006:          //return (~(XEiJ.ppiPortA >> 1 | XEiJ.ppiPortA) & 0b0101) * 0b11 | XEiJ.ppiPortA;  //上下と左右がそれぞれ同時に押されていたらキャンセルする
  5007:          if (XEiJ.regOC >> 6 != 0b0100_101_000) {  //TST.B以外。FM音源レジスタのアクセスウエイトのためのPPIの空読みはジョイスティックのデータを得ることが目的ではない
  5008:            XEiJ.ppiJoyTimeLimit = XEiJ.mpuClockTime + XEiJ.PPI_JOY_TIME_SPAN;
  5009:          }
  5010:          return XEiJ.ppiPortA;
  5011:        case 0x00e9a003:  //PPI PORT-B ジョイスティック2
  5012:          //return (~(XEiJ.ppiPortB >> 1 | XEiJ.ppiPortB) & 0b0101) * 0b11 | XEiJ.ppiPortB;  //上下と左右がそれぞれ同時に押されていたらキャンセルする
  5013:          if (XEiJ.regOC >> 6 != 0b0100_101_000) {  //TST.B以外。FM音源レジスタのアクセスウエイトのためのPPIの空読みはジョイスティックのデータを得ることが目的ではない
  5014:            XEiJ.ppiJoyTimeLimit = XEiJ.mpuClockTime + XEiJ.PPI_JOY_TIME_SPAN;
  5015:          }
  5016:          return XEiJ.ppiPortB;
  5017:        case 0x00e9a005:  //PPI PORT-C ADPCM音源,ジョイスティックコントロール
  5018:          return XEiJ.ppiPortC;
  5019:        case 0x00e9a007:  //PPIコントロール
  5020:          return 0;
  5021:        }
  5022:        return 0;
  5023:      }
  5024:     @Override protected int mmdRwz (int a) throws M68kException {
  5025:        a &= XEiJ.BUS_MOTHER_MASK;
  5026:        return mmdRbz (a) << 8 | mmdRbz (a + 1);
  5027:      }
  5028:     @Override protected int mmdRls (int a) throws M68kException {
  5029:        a &= XEiJ.BUS_MOTHER_MASK;
  5030:        return mmdRwz (a) << 16 | mmdRwz (a + 2);
  5031:      }
  5032:     //ライト
  5033:     @Override protected void mmdWb (int a, int d) throws M68kException {
  5034:        a &= XEiJ.BUS_MOTHER_MASK;
  5035:        d &= 0xff;
  5036:        switch (a) {
  5037:        case 0x00e9a001:  //PPI PORT-A ジョイスティック1
  5038:          return;
  5039:        case 0x00e9a003:  //PPI PORT-B ジョイスティック2
  5040:          return;
  5041:        case 0x00e9a005:  //PPI PORT-C ADPCM音源,ジョイスティックコントロール
  5042:          XEiJ.ppiPortC = d;
  5043:          ADPCM.pcmSetPan (d);  //パン
  5044:          ADPCM.pcmDivider = d >> 2 & 3;  //分周比。0=1/1024,1=1/768,2=1/512,3=1/768
  5045:          ADPCM.pcmUpdateRepeatInterval ();
  5046:          return;
  5047:        case 0x00e9a007:  //PPIコントロール
  5048:          if ((d & 0x80) == 0) {
  5049:            int n = (d >> 1) & 0x07;  //ビット番号
  5050:            XEiJ.ppiPortC = XEiJ.ppiPortC & ~(1 << n) | (d & 1) << n;
  5051:            if (n <= 1) {
  5052:              ADPCM.pcmSetPan (XEiJ.ppiPortC);  //パン
  5053:            } else if (n <= 3) {
  5054:              ADPCM.pcmDivider = XEiJ.ppiPortC >> 2 & 3;  //分周比。0=1/1024,1=1/768,2=1/512,3=1/768
  5055:              ADPCM.pcmUpdateRepeatInterval ();
  5056:            }
  5057:          }
  5058:          return;
  5059:        }
  5060:      }
  5061:     @Override protected void mmdWw (int a, int d) throws M68kException {
  5062:        a &= XEiJ.BUS_MOTHER_MASK;
  5063:        mmdWb (a    , d >> 8);
  5064:        mmdWb (a + 1, d     );
  5065:      }
  5066:     @Override protected void mmdWl (int a, int d) throws M68kException {
  5067:        a &= XEiJ.BUS_MOTHER_MASK;
  5068:        mmdWw (a    , d >> 16);
  5069:        mmdWw (a + 2, d      );
  5070:      }
  5071:   },  //MMD_PPI
  5072: 
  5073:   //--------------------------------------------------------------------------------
  5074:   //MMD_IOI I/O割り込み
  5075:   MMD_IOI {
  5076:     @Override public String toString () {
  5077:       return Multilingual.mlnJapanese ? "I/O 割り込み" : "I/O Interrupt";
  5078:     }
  5079:     //リード
  5080:     @Override protected int mmdRbz (int a) throws M68kException {
  5081:        a &= XEiJ.BUS_MOTHER_MASK;
  5082:        if (a == IOInterrupt.IOI_STATUS) {
  5083:          return IOInterrupt.ioiReadStatus ();
  5084:        } else if (a == IOInterrupt.IOI_VECTOR) {  //read only?
  5085:          return IOInterrupt.ioiReadVector ();
  5086:        } else {
  5087:          return super.mmdRbz (a);  //バスエラー
  5088:        }
  5089:      }
  5090:     @Override protected int mmdRwz (int a) throws M68kException {
  5091:        a &= XEiJ.BUS_MOTHER_MASK;
  5092:        return mmdRbz (a) << 8 | mmdRbz (a + 1);
  5093:      }
  5094:     @Override protected int mmdRls (int a) throws M68kException {
  5095:        a &= XEiJ.BUS_MOTHER_MASK;
  5096:        return mmdRwz (a) << 16 | mmdRwz (a + 2);
  5097:      }
  5098:     //ライト
  5099:     @Override protected void mmdWb (int a, int d) throws M68kException {
  5100:        a &= XEiJ.BUS_MOTHER_MASK;
  5101:        if (a == IOInterrupt.IOI_STATUS) {
  5102:          IOInterrupt.ioiWriteEnable (d);
  5103:        } else if (a == IOInterrupt.IOI_VECTOR) {
  5104:          IOInterrupt.ioiWriteVector (d);
  5105:        } else {
  5106:          super.mmdWb (a, d);  //バスエラー
  5107:        }
  5108:      }
  5109:     @Override protected void mmdWw (int a, int d) throws M68kException {
  5110:        a &= XEiJ.BUS_MOTHER_MASK;
  5111:        mmdWb (a    , d >> 8);
  5112:        mmdWb (a + 1, d     );
  5113:      }
  5114:     @Override protected void mmdWl (int a, int d) throws M68kException {
  5115:        a &= XEiJ.BUS_MOTHER_MASK;
  5116:        mmdWw (a    , d >> 16);
  5117:        mmdWw (a + 2, d      );
  5118:      }
  5119:   },  //MMD_IOI
  5120: 
  5121:   //--------------------------------------------------------------------------------
  5122:   //MMD_XB1 拡張ボード領域1
  5123:   MMD_XB1 {
  5124:     @Override public String toString () {
  5125:       return Multilingual.mlnJapanese ? "拡張ボード領域 1" : "Expansion Board Area 1";
  5126:     }
  5127:     //ピーク
  5128:     @Override protected int mmdPbz (int a) {
  5129:        if ((a & (XEiJ.BUS_MOTHER_MASK & -0x20)) == 0x00e9e000) {  //数値演算プロセッサボード1
  5130:          return XEiJ.fpuCoproboard1.cirPeekByteZero (a);
  5131:        }
  5132:        if ((a & (XEiJ.BUS_MOTHER_MASK & -0x20)) == 0x00e9e080) {  //数値演算プロセッサボード2
  5133:          return XEiJ.fpuCoproboard2.cirPeekByteZero (a);
  5134:        }
  5135:        if ((a & (XEiJ.BUS_MOTHER_MASK & -HFS.HFS_ROM_SIZE)) == HFS.HFS_ADDRESS) {  //ホストファイルシステムインタフェイス
  5136:          return MainMemory.mmrM8[a] & 255;
  5137:        }
  5138:        return 255;
  5139:      }
  5140:     @Override protected int mmdPwz (int a) {
  5141:        if ((a & (XEiJ.BUS_MOTHER_MASK & -0x20)) == 0x00e9e000) {  //数値演算プロセッサボード1
  5142:          return XEiJ.fpuCoproboard1.cirPeekWordZero (a);
  5143:        }
  5144:        if ((a & (XEiJ.BUS_MOTHER_MASK & -0x20)) == 0x00e9e080) {  //数値演算プロセッサボード2
  5145:          return XEiJ.fpuCoproboard2.cirPeekWordZero (a);
  5146:        }
  5147:        if ((a & (XEiJ.BUS_MOTHER_MASK & -HFS.HFS_ROM_SIZE)) == HFS.HFS_ADDRESS) {  //ホストファイルシステムインタフェイス
  5148:          return (char) (MainMemory.mmrM8[a] << 8 | MainMemory.mmrM8[a + 1] & 255);
  5149:        }
  5150:        return 65535;
  5151:      }
  5152:     @Override protected int mmdPls (int a) {
  5153:        if ((a & (XEiJ.BUS_MOTHER_MASK & -0x20)) == 0x00e9e000) {  //数値演算プロセッサボード1
  5154:          return XEiJ.fpuCoproboard1.cirPeekLong (a);
  5155:        }
  5156:        if ((a & (XEiJ.BUS_MOTHER_MASK & -0x20)) == 0x00e9e080) {  //数値演算プロセッサボード2
  5157:          return XEiJ.fpuCoproboard2.cirPeekLong (a);
  5158:        }
  5159:        if ((a & (XEiJ.BUS_MOTHER_MASK & -HFS.HFS_ROM_SIZE)) == HFS.HFS_ADDRESS) {  //ホストファイルシステムインタフェイス
  5160:          return MainMemory.mmrM8[a] << 24 | (MainMemory.mmrM8[a + 1] & 255) << 16 | (char) (MainMemory.mmrM8[a + 2] << 8 | MainMemory.mmrM8[a + 3] & 255);
  5161:        }
  5162:        return -1;
  5163:      }
  5164:     //リード
  5165:     @Override protected int mmdRbz (int a) throws M68kException {
  5166:        if ((a & (XEiJ.BUS_MOTHER_MASK & -0x20)) == 0x00e9e000) {  //数値演算プロセッサボード1
  5167:          return XEiJ.fpuCoproboard1.cirReadByteZero (a);
  5168:        }
  5169:        if ((a & (XEiJ.BUS_MOTHER_MASK & -0x20)) == 0x00e9e080) {  //数値演算プロセッサボード2
  5170:          return XEiJ.fpuCoproboard2.cirReadByteZero (a);
  5171:        }
  5172:        if ((a & (XEiJ.BUS_MOTHER_MASK & -HFS.HFS_ROM_SIZE)) == HFS.HFS_ADDRESS) {  //ホストファイルシステムインタフェイス
  5173:          return MainMemory.mmrM8[a] & 255;
  5174:        }
  5175:        return super.mmdRbz (a);  //バスエラー
  5176:      }
  5177:     @Override protected int mmdRwz (int a) throws M68kException {
  5178:        if ((a & (XEiJ.BUS_MOTHER_MASK & -0x20)) == 0x00e9e000) {  //数値演算プロセッサボード1
  5179:          return XEiJ.fpuCoproboard1.cirReadWordZero (a);
  5180:        }
  5181:        if ((a & (XEiJ.BUS_MOTHER_MASK & -0x20)) == 0x00e9e080) {  //数値演算プロセッサボード2
  5182:          return XEiJ.fpuCoproboard2.cirReadWordZero (a);
  5183:        }
  5184:        if ((a & (XEiJ.BUS_MOTHER_MASK & -HFS.HFS_ROM_SIZE)) == HFS.HFS_ADDRESS) {  //ホストファイルシステムインタフェイス
  5185:          return (char) (MainMemory.mmrM8[a] << 8 | MainMemory.mmrM8[a + 1] & 255);
  5186:        }
  5187:        return super.mmdRwz (a);  //バスエラー
  5188:      }
  5189:     @Override protected int mmdRls (int a) throws M68kException {
  5190:        if ((a & (XEiJ.BUS_MOTHER_MASK & -0x20)) == 0x00e9e000) {  //数値演算プロセッサボード1
  5191:          return XEiJ.fpuCoproboard1.cirReadLong (a);
  5192:        }
  5193:        if ((a & (XEiJ.BUS_MOTHER_MASK & -0x20)) == 0x00e9e080) {  //数値演算プロセッサボード2
  5194:          return XEiJ.fpuCoproboard2.cirReadLong (a);
  5195:        }
  5196:        if ((a & (XEiJ.BUS_MOTHER_MASK & -HFS.HFS_ROM_SIZE)) == HFS.HFS_ADDRESS) {  //ホストファイルシステムインタフェイス
  5197:          return MainMemory.mmrM8[a] << 24 | (MainMemory.mmrM8[a + 1] & 255) << 16 | (char) (MainMemory.mmrM8[a + 2] << 8 | MainMemory.mmrM8[a + 3] & 255);
  5198:        }
  5199:        return super.mmdRls (a);  //バスエラー
  5200:      }
  5201:     //ライト
  5202:     @Override protected void mmdWb (int a, int d) throws M68kException {
  5203:        if ((a & (XEiJ.BUS_MOTHER_MASK & -0x20)) == 0x00e9e000) {  //数値演算プロセッサボード1
  5204:          XEiJ.fpuCoproboard1.cirWriteByte (a, d);
  5205:          return;
  5206:        }
  5207:        if ((a & (XEiJ.BUS_MOTHER_MASK & -0x20)) == 0x00e9e080) {  //数値演算プロセッサボード2
  5208:          XEiJ.fpuCoproboard2.cirWriteByte (a, d);
  5209:          return;
  5210:        }
  5211:        super.mmdWb (a, d);  //バスエラー
  5212:      }
  5213:     @Override protected void mmdWw (int a, int d) throws M68kException {
  5214:        if ((a & (XEiJ.BUS_MOTHER_MASK & -0x20)) == 0x00e9e000) {  //数値演算プロセッサボード1
  5215:          XEiJ.fpuCoproboard1.cirWriteWord (a, d);
  5216:          return;
  5217:        }
  5218:        if ((a & (XEiJ.BUS_MOTHER_MASK & -0x20)) == 0x00e9e080) {  //数値演算プロセッサボード2
  5219:          XEiJ.fpuCoproboard2.cirWriteWord (a, d);
  5220:          return;
  5221:        }
  5222:        super.mmdWw (a, d);  //バスエラー
  5223:      }
  5224:     @Override protected void mmdWl (int a, int d) throws M68kException {
  5225:        if ((a & (XEiJ.BUS_MOTHER_MASK & -0x20)) == 0x00e9e000) {  //数値演算プロセッサボード1
  5226:          XEiJ.fpuCoproboard1.cirWriteLong (a, d);
  5227:          return;
  5228:        }
  5229:        if ((a & (XEiJ.BUS_MOTHER_MASK & -0x20)) == 0x00e9e080) {  //数値演算プロセッサボード2
  5230:          XEiJ.fpuCoproboard2.cirWriteLong (a, d);
  5231:          return;
  5232:        }
  5233:        super.mmdWl (a, d);  //バスエラー
  5234:      }
  5235:   },  //MMD_XB1
  5236: 
  5237:   //--------------------------------------------------------------------------------
  5238:   //MMD_EXS 拡張SCSI
  5239:   //  必要なときだけ接続される
  5240:   //  拡張SCSIのROMのサイズは8KBなのでリードのときのバスエラーのチェックは不要
  5241:   //  ライトのときはROMには書き込めないのでSPCのレジスタでなければバスエラー
  5242:   MMD_EXS {
  5243:     @Override public String toString () {
  5244:       return Multilingual.mlnJapanese ? "拡張 SCSI ポート" : "Expansion SCSI Port";
  5245:     }
  5246:     //ピーク
  5247:     @Override protected byte mmdPbs (int a) {
  5248:       a &= XEiJ.BUS_MOTHER_MASK;
  5249:        return (a & -32) == SPC.SPC_BASE_EX ? (byte) SPC.spcSCSIEXChip.spiPeek (a) : MainMemory.mmrM8[a];
  5250:      }
  5251:     @Override protected int mmdPbz (int a) {
  5252:       a &= XEiJ.BUS_MOTHER_MASK;
  5253:        return (a & -32) == SPC.SPC_BASE_EX ? SPC.spcSCSIEXChip.spiPeek (a) : MainMemory.mmrM8[a] & 255;
  5254:      }
  5255:     @Override protected int mmdPws (int a) {
  5256:       a &= XEiJ.BUS_MOTHER_MASK;
  5257:        return mmdPbs (a) << 8 | mmdPbz (a + 1);
  5258:      }
  5259:     @Override protected int mmdPwz (int a) {
  5260:       a &= XEiJ.BUS_MOTHER_MASK;
  5261:        return mmdPbz (a) << 8 | mmdPbz (a + 1);
  5262:      }
  5263:     @Override protected int mmdPls (int a) {
  5264:       a &= XEiJ.BUS_MOTHER_MASK;
  5265:        return mmdPbs (a) << 24 | mmdPbz (a + 1) << 16 | mmdPbz (a + 2) << 8 | mmdPbz (a + 3);
  5266:      }
  5267:     //リード
  5268:     @Override protected byte mmdRbs (int a) throws M68kException {
  5269:        a &= XEiJ.BUS_MOTHER_MASK;
  5270:        return (a & -32) == SPC.SPC_BASE_EX ? (byte) SPC.spcSCSIEXChip.spiRead (a) : MainMemory.mmrM8[a];
  5271:      }
  5272:     @Override protected int mmdRbz (int a) throws M68kException {
  5273:        a &= XEiJ.BUS_MOTHER_MASK;
  5274:        return (a & -32) == SPC.SPC_BASE_EX ? SPC.spcSCSIEXChip.spiRead (a) : MainMemory.mmrM8[a] & 255;
  5275:      }
  5276:     @Override protected int mmdRws (int a) throws M68kException {
  5277:        a &= XEiJ.BUS_MOTHER_MASK;
  5278:        return mmdRbs (a) << 8 | mmdRbz (a + 1);
  5279:      }
  5280:     @Override protected int mmdRwz (int a) throws M68kException {
  5281:        a &= XEiJ.BUS_MOTHER_MASK;
  5282:        return mmdRbz (a) << 8 | mmdRbz (a + 1);
  5283:      }
  5284:     @Override protected int mmdRls (int a) throws M68kException {
  5285:        a &= XEiJ.BUS_MOTHER_MASK;
  5286:        return mmdRbs (a) << 24 | mmdRbz (a + 1) << 16 | mmdRbz (a + 2) << 8 | mmdRbz (a + 3);
  5287:      }
  5288:     //ライト
  5289:     @Override protected void mmdWb (int a, int d) throws M68kException {
  5290:        a &= XEiJ.BUS_MOTHER_MASK;
  5291:        if ((a & -32) == SPC.SPC_BASE_EX) {
  5292:          SPC.spcSCSIEXChip.spiWrite (a, d);
  5293:          return;
  5294:        }
  5295:        super.mmdWb (a, d);  //バスエラー
  5296:      }
  5297:     @Override protected void mmdWw (int a, int d) throws M68kException {
  5298:        a &= XEiJ.BUS_MOTHER_MASK;
  5299:        mmdWb (a    , d >> 8);
  5300:        mmdWb (a + 1, d     );
  5301:      }
  5302:     @Override protected void mmdWl (int a, int d) throws M68kException {
  5303:        a &= XEiJ.BUS_MOTHER_MASK;
  5304:        mmdWw (a    , d >> 16);
  5305:        mmdWw (a + 2, d      );
  5306:      }
  5307:   },  //MMD_EXS
  5308: 
  5309:   //--------------------------------------------------------------------------------
  5310:   //MMD_XB2 拡張ボード領域2
  5311:   MMD_XB2 {
  5312:     @Override public String toString () {
  5313:       return Multilingual.mlnJapanese ? "拡張ボード領域 2" : "Expansion Board Area 2";
  5314:     }
  5315:     //リード
  5316:     @Override protected int mmdRbz (int a) throws M68kException {
  5317:        a &= XEiJ.BUS_MOTHER_MASK;
  5318:        if (0x00eaff81 <= a && a <= 0x00eaff89 && (a & 1) != 0) {  //スーパーバイザエリア設定ポート
  5319:          return MainMemory.mmrM8[a] & 255;  //読み出せるようにしておく(本来はライトオンリー)
  5320:        }
  5321:        return super.mmdRbz (a);  //バスエラー
  5322:      }
  5323:     //ライト
  5324:     @Override protected void mmdWb (int a, int d) throws M68kException {
  5325:        a &= XEiJ.BUS_MOTHER_MASK;
  5326:        if (0x00eaff81 <= a && a <= 0x00eaff89 && (a & 1) != 0) {  //スーパーバイザエリア設定ポート
  5327:          MainMemory.mmrM8[a] = (byte) d;  //読み出せるようにしておく(本来はライトオンリー)
  5328:          a = (a & 14) + 2 << 20;  //1,3,5,7,9→2,4,6,8,a
  5329:          for (int m = 1; m <= 128; m <<= 1) {
  5330:            if ((d & m) == 0) {  //ユーザエリア
  5331:              XEiJ.busUser ( MemoryMappedDevice.MMD_MMR, a, a + 0x00040000);
  5332:            } else {  //スーパーバイザエリア
  5333:              XEiJ.busSuper (MemoryMappedDevice.MMD_MMR, a, a + 0x00040000);
  5334:            }
  5335:            a += 0x00040000;
  5336:          }
  5337:          return;
  5338:        }
  5339:        super.mmdWb (a, d);  //バスエラー
  5340:      }
  5341:   },  //MMD_XB2
  5342: 
  5343:   //--------------------------------------------------------------------------------
  5344:   //MMD_SPR スプライト画面
  5345:   MMD_SPR {
  5346:     @Override public String toString () {
  5347:       return Multilingual.mlnJapanese ? "スプライト画面" : "Sprite Screen";
  5348:     }
  5349:     //リード
  5350:     @Override protected byte mmdRbs (int a) throws M68kException {
  5351:        a &= XEiJ.BUS_MOTHER_MASK;
  5352:        return (byte) ((XEiJ.TEST_BIT_0_SHIFT ? a << 31 - 0 >= 0 : (a & 1) == 0) ? mmdRwz (a) >> 8 : mmdRwz (a - 1) & 255);
  5353:      }
  5354:     @Override protected int mmdRbz (int a) throws M68kException {
  5355:        a &= XEiJ.BUS_MOTHER_MASK;
  5356:        return (XEiJ.TEST_BIT_0_SHIFT ? a << 31 - 0 >= 0 : (a & 1) == 0) ? mmdRwz (a) >> 8 : mmdRwz (a - 1) & 255;
  5357:      }
  5358:     @Override protected int mmdRws (int a) throws M68kException {
  5359:        a &= XEiJ.BUS_MOTHER_MASK;
  5360:        return (short) mmdRwz (a);
  5361:      }
  5362:     @Override protected int mmdRwz (int a) throws M68kException {
  5363:        a &= XEiJ.BUS_MOTHER_MASK;
  5364:        if (a < 0x00eb0400) {  //スプライトスクロールレジスタ
  5365:          int n = (a >> 3) & 0x7f;
  5366:          switch (a & 0x06) {
  5367:          case 0:  //x座標
  5368:            return SpriteScreen.sprX[n];
  5369:          case 2:  //y座標
  5370:            return SpriteScreen.sprY[n];
  5371:          case 4:  //パターン番号、パレットブロック、水平反転、垂直反転
  5372:            return (SpriteScreen.sprV[n] ? 0x8000 : 0) | (SpriteScreen.sprH[n] ? 0x4000 : 0) | SpriteScreen.sprColPort[n] << 4 | SpriteScreen.sprNum[n];
  5373:          case 6:  //プライオリティ
  5374:            return SpriteScreen.sprPrw[n];
  5375:          }
  5376:        } else if (a < 0x00eb8000) {  //各種レジスタ
  5377:          switch (a) {
  5378:          case SpriteScreen.SPR_REG0_BG0_X:
  5379:            return SpriteScreen.sprReg0Bg0XPort;
  5380:          case SpriteScreen.SPR_REG1_BG0_Y:
  5381:            return SpriteScreen.sprReg1Bg0YPort;
  5382:          case SpriteScreen.SPR_REG2_BG1_X:
  5383:            return SpriteScreen.sprReg2Bg1XPort;
  5384:          case SpriteScreen.SPR_REG3_BG1_Y:
  5385:            return SpriteScreen.sprReg3Bg1YPort;
  5386:          case SpriteScreen.SPR_REG4_BG_CTRL:
  5387:            return SpriteScreen.sprReg4BgCtrlPort;
  5388:          case SpriteScreen.SPR_REG5_H_TOTAL:
  5389:            return SpriteScreen.sprReg5HTotalPort;
  5390:          case SpriteScreen.SPR_REG6_H_START:
  5391:            return SpriteScreen.sprReg6HStartPort;
  5392:          case SpriteScreen.SPR_REG7_V_START:
  5393:            return SpriteScreen.sprReg7VStartPort;
  5394:          case SpriteScreen.SPR_REG8_RESO:
  5395:            return SpriteScreen.sprReg8ResoPort;
  5396:          }
  5397:          return 0;
  5398:        } else {  //PCGエリアとテキストエリア
  5399:          int t = a >> 2 & 0x1fff;
  5400:          return (a & 0x02) == 0 ? SpriteScreen.sprPatPort[t] >>> 16 : (char) SpriteScreen.sprPatPort[t];
  5401:        }
  5402:        return 0;
  5403:      }
  5404:     @Override protected int mmdRls (int a) throws M68kException {
  5405:        a &= XEiJ.BUS_MOTHER_MASK;
  5406:        return mmdRwz (a) << 16 | mmdRwz (a + 2);
  5407:      }
  5408:     //ライト
  5409:     @Override protected void mmdWb (int a, int d) throws M68kException {
  5410:        a &= XEiJ.BUS_MOTHER_MASK;
  5411:        if (XEiJ.TEST_BIT_0_SHIFT ? a << 31 - 0 >= 0 : (a & 1) == 0) {
  5412:          mmdWw (a, d << 8 | mmdRwz (a) & 255);
  5413:        } else {
  5414:          mmdWw (a - 1, mmdRwz (a - 1) & 0xff00 | d & 255);
  5415:        }
  5416:      }
  5417:     @Override protected void mmdWw (int a, int d) throws M68kException {
  5418:        a &= XEiJ.BUS_MOTHER_MASK;
  5419:        if (a < 0x00eb0400) {  //スプライトスクロールレジスタ
  5420:          int n = a >> 3 & 0x7f;  //スプライト番号
  5421:          switch (a & 0x06) {
  5422:          case 0:  //x座標
  5423:            SpriteScreen.sprX[n] = (short) (d & 1023);
  5424: /*
  5425:            if (SpriteScreen.sprPrw[n] != 0 &&
  5426:                VideoController.vcnReg3Curr << 31 - 6 < 0 &&  //スプライト画面が表示されている
  5427:                SpriteScreen.sprReg4BgCtrlCurr << 31 - 9 < 0) {  //スプライト画面が表示されている
  5428:              int y = SpriteScreen.sprY[n];
  5429:              if (true) {
  5430:                if (y < 16) {
  5431:                  for (int i = 0; i < y; i++) {
  5432:                    CRTC.crtRasterStamp[i] = 0;
  5433:                  }
  5434:                } else {
  5435:                  CRTC.crtRasterStamp[y - 16] = 0;
  5436:                  CRTC.crtRasterStamp[y - 15] = 0;
  5437:                  CRTC.crtRasterStamp[y - 14] = 0;
  5438:                  CRTC.crtRasterStamp[y - 13] = 0;
  5439:                  CRTC.crtRasterStamp[y - 12] = 0;
  5440:                  CRTC.crtRasterStamp[y - 11] = 0;
  5441:                  CRTC.crtRasterStamp[y - 10] = 0;
  5442:                  CRTC.crtRasterStamp[y -  9] = 0;
  5443:                  CRTC.crtRasterStamp[y -  8] = 0;
  5444:                  CRTC.crtRasterStamp[y -  7] = 0;
  5445:                  CRTC.crtRasterStamp[y -  6] = 0;
  5446:                  CRTC.crtRasterStamp[y -  5] = 0;
  5447:                  CRTC.crtRasterStamp[y -  4] = 0;
  5448:                  CRTC.crtRasterStamp[y -  3] = 0;
  5449:                  CRTC.crtRasterStamp[y -  2] = 0;
  5450:                  CRTC.crtRasterStamp[y -  1] = 0;
  5451:                }
  5452:              } else {
  5453:                Arrays.fill (CRTC.crtRasterStamp, y < 16 ? 0 : y - 16, y, 0);
  5454:              }
  5455:            }
  5456: */
  5457:            break;
  5458:          case 2:  //y座標
  5459:            d &= 1023;
  5460:            if (SpriteScreen.sprY[n] != d) {
  5461:              int y = SpriteScreen.sprY[n];
  5462:              SpriteScreen.sprY[n] = (short) d;
  5463:              if (SpriteScreen.sprPrw[n] != 0) {
  5464:                if (SpriteScreen.SPR_RRMAP) {
  5465:                  int mask = ~(0x80000000 >>> n);  //intのシフトカウントは5bitでマスクされる
  5466:                  int i = y << 2 | n >> 5;
  5467:                  SpriteScreen.sprRRmap[i            ] &= mask;
  5468:                  SpriteScreen.sprRRmap[i + ( 1 << 2)] &= mask;
  5469:                  SpriteScreen.sprRRmap[i + ( 2 << 2)] &= mask;
  5470:                  SpriteScreen.sprRRmap[i + ( 3 << 2)] &= mask;
  5471:                  SpriteScreen.sprRRmap[i + ( 4 << 2)] &= mask;
  5472:                  SpriteScreen.sprRRmap[i + ( 5 << 2)] &= mask;
  5473:                  SpriteScreen.sprRRmap[i + ( 6 << 2)] &= mask;
  5474:                  SpriteScreen.sprRRmap[i + ( 7 << 2)] &= mask;
  5475:                  SpriteScreen.sprRRmap[i + ( 8 << 2)] &= mask;
  5476:                  SpriteScreen.sprRRmap[i + ( 9 << 2)] &= mask;
  5477:                  SpriteScreen.sprRRmap[i + (10 << 2)] &= mask;
  5478:                  SpriteScreen.sprRRmap[i + (11 << 2)] &= mask;
  5479:                  SpriteScreen.sprRRmap[i + (12 << 2)] &= mask;
  5480:                  SpriteScreen.sprRRmap[i + (13 << 2)] &= mask;
  5481:                  SpriteScreen.sprRRmap[i + (14 << 2)] &= mask;
  5482:                  SpriteScreen.sprRRmap[i + (15 << 2)] &= mask;
  5483:                  mask = ~mask;
  5484:                  i = d << 2 | n >> 5;
  5485:                  SpriteScreen.sprRRmap[i            ] |= mask;
  5486:                  SpriteScreen.sprRRmap[i + ( 1 << 2)] |= mask;
  5487:                  SpriteScreen.sprRRmap[i + ( 2 << 2)] |= mask;
  5488:                  SpriteScreen.sprRRmap[i + ( 3 << 2)] |= mask;
  5489:                  SpriteScreen.sprRRmap[i + ( 4 << 2)] |= mask;
  5490:                  SpriteScreen.sprRRmap[i + ( 5 << 2)] |= mask;
  5491:                  SpriteScreen.sprRRmap[i + ( 6 << 2)] |= mask;
  5492:                  SpriteScreen.sprRRmap[i + ( 7 << 2)] |= mask;
  5493:                  SpriteScreen.sprRRmap[i + ( 8 << 2)] |= mask;
  5494:                  SpriteScreen.sprRRmap[i + ( 9 << 2)] |= mask;
  5495:                  SpriteScreen.sprRRmap[i + (10 << 2)] |= mask;
  5496:                  SpriteScreen.sprRRmap[i + (11 << 2)] |= mask;
  5497:                  SpriteScreen.sprRRmap[i + (12 << 2)] |= mask;
  5498:                  SpriteScreen.sprRRmap[i + (13 << 2)] |= mask;
  5499:                  SpriteScreen.sprRRmap[i + (14 << 2)] |= mask;
  5500:                  SpriteScreen.sprRRmap[i + (15 << 2)] |= mask;
  5501:                } else {  //!SpriteScreen.SPR_RRMAP
  5502:                  int[] map = SpriteScreen.sprRmap[n >> 5];
  5503:                  int mask = ~(1 << n);  //intのシフトカウントは5bitでマスクされる
  5504:                  map[y     ] &= mask;
  5505:                  map[y +  1] &= mask;
  5506:                  map[y +  2] &= mask;
  5507:                  map[y +  3] &= mask;
  5508:                  map[y +  4] &= mask;
  5509:                  map[y +  5] &= mask;
  5510:                  map[y +  6] &= mask;
  5511:                  map[y +  7] &= mask;
  5512:                  map[y +  8] &= mask;
  5513:                  map[y +  9] &= mask;
  5514:                  map[y + 10] &= mask;
  5515:                  map[y + 11] &= mask;
  5516:                  map[y + 12] &= mask;
  5517:                  map[y + 13] &= mask;
  5518:                  map[y + 14] &= mask;
  5519:                  map[y + 15] &= mask;
  5520:                  mask = ~mask;
  5521:                  map[d     ] |= mask;
  5522:                  map[d +  1] |= mask;
  5523:                  map[d +  2] |= mask;
  5524:                  map[d +  3] |= mask;
  5525:                  map[d +  4] |= mask;
  5526:                  map[d +  5] |= mask;
  5527:                  map[d +  6] |= mask;
  5528:                  map[d +  7] |= mask;
  5529:                  map[d +  8] |= mask;
  5530:                  map[d +  9] |= mask;
  5531:                  map[d + 10] |= mask;
  5532:                  map[d + 11] |= mask;
  5533:                  map[d + 12] |= mask;
  5534:                  map[d + 13] |= mask;
  5535:                  map[d + 14] |= mask;
  5536:                  map[d + 15] |= mask;
  5537:                }  //if SpriteScreen.SPR_RRMAP/!SpriteScreen.SPR_RRMAP
  5538: /*
  5539:                if (VideoController.vcnReg3Curr << 31 - 6 < 0 &&  //スプライト画面が表示されている
  5540:                    SpriteScreen.sprReg4BgCtrlCurr << 31 - 9 < 0) {  //スプライト画面が表示されている
  5541:                  if (true) {
  5542:                    if (y < 16) {
  5543:                      for (int i = 0; i < y; i++) {
  5544:                        CRTC.crtRasterStamp[i] = 0;
  5545:                      }
  5546:                    } else {
  5547:                      CRTC.crtRasterStamp[y - 16] = 0;
  5548:                      CRTC.crtRasterStamp[y - 15] = 0;
  5549:                      CRTC.crtRasterStamp[y - 14] = 0;
  5550:                      CRTC.crtRasterStamp[y - 13] = 0;
  5551:                      CRTC.crtRasterStamp[y - 12] = 0;
  5552:                      CRTC.crtRasterStamp[y - 11] = 0;
  5553:                      CRTC.crtRasterStamp[y - 10] = 0;
  5554:                      CRTC.crtRasterStamp[y -  9] = 0;
  5555:                      CRTC.crtRasterStamp[y -  8] = 0;
  5556:                      CRTC.crtRasterStamp[y -  7] = 0;
  5557:                      CRTC.crtRasterStamp[y -  6] = 0;
  5558:                      CRTC.crtRasterStamp[y -  5] = 0;
  5559:                      CRTC.crtRasterStamp[y -  4] = 0;
  5560:                      CRTC.crtRasterStamp[y -  3] = 0;
  5561:                      CRTC.crtRasterStamp[y -  2] = 0;
  5562:                      CRTC.crtRasterStamp[y -  1] = 0;
  5563:                    }
  5564:                  } else {
  5565:                    Arrays.fill (CRTC.crtRasterStamp, y < 16 ? 0 : y - 16, y, 0);
  5566:                  }
  5567:                  if (true) {
  5568:                    if (d < 16) {
  5569:                      for (int i = 0; i < d; i++) {
  5570:                        CRTC.crtRasterStamp[i] = 0;
  5571:                      }
  5572:                    } else {
  5573:                      CRTC.crtRasterStamp[d - 16] = 0;
  5574:                      CRTC.crtRasterStamp[d - 15] = 0;
  5575:                      CRTC.crtRasterStamp[d - 14] = 0;
  5576:                      CRTC.crtRasterStamp[d - 13] = 0;
  5577:                      CRTC.crtRasterStamp[d - 12] = 0;
  5578:                      CRTC.crtRasterStamp[d - 11] = 0;
  5579:                      CRTC.crtRasterStamp[d - 10] = 0;
  5580:                      CRTC.crtRasterStamp[d -  9] = 0;
  5581:                      CRTC.crtRasterStamp[d -  8] = 0;
  5582:                      CRTC.crtRasterStamp[d -  7] = 0;
  5583:                      CRTC.crtRasterStamp[d -  6] = 0;
  5584:                      CRTC.crtRasterStamp[d -  5] = 0;
  5585:                      CRTC.crtRasterStamp[d -  4] = 0;
  5586:                      CRTC.crtRasterStamp[d -  3] = 0;
  5587:                      CRTC.crtRasterStamp[d -  2] = 0;
  5588:                      CRTC.crtRasterStamp[d -  1] = 0;
  5589:                    }
  5590:                  } else {
  5591:                    Arrays.fill (CRTC.crtRasterStamp, d < 16 ? 0 : d - 16, d, 0);
  5592:                  }
  5593:                }
  5594: */
  5595:              }
  5596:            }
  5597:            break;
  5598:          case 4:  //パターン番号、パレットブロック、水平反転、垂直反転
  5599:            {
  5600:              int num = SpriteScreen.sprNum[n];
  5601:              SpriteScreen.sprNum[n] = (short) (d & 255);
  5602:              SpriteScreen.sprColPort[n] = (short) (d >> 4 & 0x0f << 4);
  5603:              SpriteScreen.sprH[n] = (short) (d << 1) < 0;
  5604:              SpriteScreen.sprV[n] = (short) d < 0;
  5605:              if (SpriteScreen.sprPrw[n] != 0) {
  5606:                if (SpriteScreen.SPR_RRMAP) {
  5607:                  int mask = 0x80000000 >>> n;  //intのシフトカウントは5bitでマスクされる
  5608:                  SpriteScreen.sprPPmap[num << 2 | n >> 5] -= mask;
  5609:                  SpriteScreen.sprPPmap[(d & 255) << 2 | n >> 5] += mask;
  5610:                } else {
  5611:                  int[] map = SpriteScreen.sprPmap[n >> 5];
  5612:                  int mask = 1 << n;  //intのシフトカウントは5bitでマスクされる
  5613:                  map[num] -= mask;
  5614:                  map[d & 255] += mask;
  5615:                }
  5616: /*
  5617:                if (VideoController.vcnReg3Curr << 31 - 6 < 0 &&  //スプライト画面が表示されている
  5618:                    SpriteScreen.sprReg4BgCtrlCurr << 31 - 9 < 0) {  //スプライト画面が表示されている
  5619:                  int y = SpriteScreen.sprY[n];
  5620:                  if (true) {
  5621:                    if (y < 16) {
  5622:                      for (int i = 0; i < y; i++) {
  5623:                        CRTC.crtRasterStamp[i] = 0;
  5624:                      }
  5625:                    } else {
  5626:                      CRTC.crtRasterStamp[y - 16] = 0;
  5627:                      CRTC.crtRasterStamp[y - 15] = 0;
  5628:                      CRTC.crtRasterStamp[y - 14] = 0;
  5629:                      CRTC.crtRasterStamp[y - 13] = 0;
  5630:                      CRTC.crtRasterStamp[y - 12] = 0;
  5631:                      CRTC.crtRasterStamp[y - 11] = 0;
  5632:                      CRTC.crtRasterStamp[y - 10] = 0;
  5633:                      CRTC.crtRasterStamp[y -  9] = 0;
  5634:                      CRTC.crtRasterStamp[y -  8] = 0;
  5635:                      CRTC.crtRasterStamp[y -  7] = 0;
  5636:                      CRTC.crtRasterStamp[y -  6] = 0;
  5637:                      CRTC.crtRasterStamp[y -  5] = 0;
  5638:                      CRTC.crtRasterStamp[y -  4] = 0;
  5639:                      CRTC.crtRasterStamp[y -  3] = 0;
  5640:                      CRTC.crtRasterStamp[y -  2] = 0;
  5641:                      CRTC.crtRasterStamp[y -  1] = 0;
  5642:                    }
  5643:                  } else {
  5644:                    Arrays.fill (CRTC.crtRasterStamp, y < 16 ? 0 : y - 16, y, 0);
  5645:                  }
  5646:                }
  5647: */
  5648:              }
  5649:            }
  5650:            break;
  5651:          case 6:  //プライオリティ
  5652:            d &= 0x0003;
  5653:            int prw = SpriteScreen.sprPrw[n];
  5654:            SpriteScreen.sprPrw[n] = (byte) d;
  5655:            if (prw != d) {
  5656:              if (prw == 0) {  //出現
  5657:                int y = SpriteScreen.sprY[n];
  5658:                if (SpriteScreen.SPR_RRMAP) {
  5659:                  int mask = 0x80000000 >>> n;  //intのシフトカウントは5bitでマスクされる
  5660:                  int i = y << 2 | n >> 5;
  5661:                  SpriteScreen.sprRRmap[i            ] |= mask;
  5662:                  SpriteScreen.sprRRmap[i + ( 1 << 2)] |= mask;
  5663:                  SpriteScreen.sprRRmap[i + ( 2 << 2)] |= mask;
  5664:                  SpriteScreen.sprRRmap[i + ( 3 << 2)] |= mask;
  5665:                  SpriteScreen.sprRRmap[i + ( 4 << 2)] |= mask;
  5666:                  SpriteScreen.sprRRmap[i + ( 5 << 2)] |= mask;
  5667:                  SpriteScreen.sprRRmap[i + ( 6 << 2)] |= mask;
  5668:                  SpriteScreen.sprRRmap[i + ( 7 << 2)] |= mask;
  5669:                  SpriteScreen.sprRRmap[i + ( 8 << 2)] |= mask;
  5670:                  SpriteScreen.sprRRmap[i + ( 9 << 2)] |= mask;
  5671:                  SpriteScreen.sprRRmap[i + (10 << 2)] |= mask;
  5672:                  SpriteScreen.sprRRmap[i + (11 << 2)] |= mask;
  5673:                  SpriteScreen.sprRRmap[i + (12 << 2)] |= mask;
  5674:                  SpriteScreen.sprRRmap[i + (13 << 2)] |= mask;
  5675:                  SpriteScreen.sprRRmap[i + (14 << 2)] |= mask;
  5676:                  SpriteScreen.sprRRmap[i + (15 << 2)] |= mask;
  5677:                  SpriteScreen.sprPPmap[SpriteScreen.sprNum[n] << 2 | n >> 5] |= mask;
  5678:                } else {  //!SpriteScreen.SPR_RRMAP
  5679:                  int map[] = SpriteScreen.sprRmap[n >> 5];
  5680:                  int mask = 1 << n;  //intのシフトカウントは5bitでマスクされる
  5681:                  map[y     ] |= mask;
  5682:                  map[y +  1] |= mask;
  5683:                  map[y +  2] |= mask;
  5684:                  map[y +  3] |= mask;
  5685:                  map[y +  4] |= mask;
  5686:                  map[y +  5] |= mask;
  5687:                  map[y +  6] |= mask;
  5688:                  map[y +  7] |= mask;
  5689:                  map[y +  8] |= mask;
  5690:                  map[y +  9] |= mask;
  5691:                  map[y + 10] |= mask;
  5692:                  map[y + 11] |= mask;
  5693:                  map[y + 12] |= mask;
  5694:                  map[y + 13] |= mask;
  5695:                  map[y + 14] |= mask;
  5696:                  map[y + 15] |= mask;
  5697:                  SpriteScreen.sprPmap[n >> 5][SpriteScreen.sprNum[n]] |= mask;
  5698:                }  //if SpriteScreen.SPR_RRMAP/!SpriteScreen.SPR_RRMAP
  5699:              } else if (d == 0) {  //消滅
  5700:                int y = SpriteScreen.sprY[n];
  5701:                if (SpriteScreen.SPR_RRMAP) {
  5702:                  int mask = ~(0x80000000 >>> n);  //intのシフトカウントは5bitでマスクされる
  5703:                  int i = y << 2 | n >> 5;
  5704:                  SpriteScreen.sprRRmap[i            ] &= mask;
  5705:                  SpriteScreen.sprRRmap[i + ( 1 << 2)] &= mask;
  5706:                  SpriteScreen.sprRRmap[i + ( 2 << 2)] &= mask;
  5707:                  SpriteScreen.sprRRmap[i + ( 3 << 2)] &= mask;
  5708:                  SpriteScreen.sprRRmap[i + ( 4 << 2)] &= mask;
  5709:                  SpriteScreen.sprRRmap[i + ( 5 << 2)] &= mask;
  5710:                  SpriteScreen.sprRRmap[i + ( 6 << 2)] &= mask;
  5711:                  SpriteScreen.sprRRmap[i + ( 7 << 2)] &= mask;
  5712:                  SpriteScreen.sprRRmap[i + ( 8 << 2)] &= mask;
  5713:                  SpriteScreen.sprRRmap[i + ( 9 << 2)] &= mask;
  5714:                  SpriteScreen.sprRRmap[i + (10 << 2)] &= mask;
  5715:                  SpriteScreen.sprRRmap[i + (11 << 2)] &= mask;
  5716:                  SpriteScreen.sprRRmap[i + (12 << 2)] &= mask;
  5717:                  SpriteScreen.sprRRmap[i + (13 << 2)] &= mask;
  5718:                  SpriteScreen.sprRRmap[i + (14 << 2)] &= mask;
  5719:                  SpriteScreen.sprRRmap[i + (15 << 2)] &= mask;
  5720:                  SpriteScreen.sprPPmap[SpriteScreen.sprNum[n] << 2 | n >> 5] &= mask;
  5721:                } else {  //!SpriteScreen.SPR_RRMAP
  5722:                  int map[] = SpriteScreen.sprRmap[n >> 5];
  5723:                  int mask = ~(1 << n);  //intのシフトカウントは5bitでマスクされる
  5724:                  map[y     ] &= mask;
  5725:                  map[y +  1] &= mask;
  5726:                  map[y +  2] &= mask;
  5727:                  map[y +  3] &= mask;
  5728:                  map[y +  4] &= mask;
  5729:                  map[y +  5] &= mask;
  5730:                  map[y +  6] &= mask;
  5731:                  map[y +  7] &= mask;
  5732:                  map[y +  8] &= mask;
  5733:                  map[y +  9] &= mask;
  5734:                  map[y + 10] &= mask;
  5735:                  map[y + 11] &= mask;
  5736:                  map[y + 12] &= mask;
  5737:                  map[y + 13] &= mask;
  5738:                  map[y + 14] &= mask;
  5739:                  map[y + 15] &= mask;
  5740:                  SpriteScreen.sprPmap[n >> 5][SpriteScreen.sprNum[n]] &= mask;
  5741:                }  //if SpriteScreen.SPR_RRMAP/!SpriteScreen.SPR_RRMAP
  5742:              }
  5743: /*
  5744:              if (VideoController.vcnReg3Curr << 31 - 6 < 0 &&  //スプライト画面が表示されている
  5745:                  SpriteScreen.sprReg4BgCtrlCurr << 31 - 9 < 0) {  //スプライト画面が表示されている
  5746:                int y = SpriteScreen.sprY[n];
  5747:                if (true) {
  5748:                  if (y < 16) {
  5749:                    for (int i = 0; i < y; i++) {
  5750:                      CRTC.crtRasterStamp[i] = 0;
  5751:                    }
  5752:                  } else {
  5753:                    CRTC.crtRasterStamp[y - 16] = 0;
  5754:                    CRTC.crtRasterStamp[y - 15] = 0;
  5755:                    CRTC.crtRasterStamp[y - 14] = 0;
  5756:                    CRTC.crtRasterStamp[y - 13] = 0;
  5757:                    CRTC.crtRasterStamp[y - 12] = 0;
  5758:                    CRTC.crtRasterStamp[y - 11] = 0;
  5759:                    CRTC.crtRasterStamp[y - 10] = 0;
  5760:                    CRTC.crtRasterStamp[y -  9] = 0;
  5761:                    CRTC.crtRasterStamp[y -  8] = 0;
  5762:                    CRTC.crtRasterStamp[y -  7] = 0;
  5763:                    CRTC.crtRasterStamp[y -  6] = 0;
  5764:                    CRTC.crtRasterStamp[y -  5] = 0;
  5765:                    CRTC.crtRasterStamp[y -  4] = 0;
  5766:                    CRTC.crtRasterStamp[y -  3] = 0;
  5767:                    CRTC.crtRasterStamp[y -  2] = 0;
  5768:                    CRTC.crtRasterStamp[y -  1] = 0;
  5769:                  }
  5770:                } else {
  5771:                  Arrays.fill (CRTC.crtRasterStamp, y < 16 ? 0 : y - 16, y, 0);
  5772:                }
  5773:              }
  5774: */
  5775:            }
  5776:            break;
  5777:          }  //スプライトスクロールレジスタのswitch
  5778:          return;
  5779:        } else if (a < 0x00eb8000) {  //各種レジスタ
  5780:          switch (a) {
  5781:          case SpriteScreen.SPR_REG0_BG0_X:
  5782:            SpriteScreen.sprReg0Bg0XPort = d & 1023;
  5783:            {
  5784:              int curr = SpriteScreen.sprReg0Bg0XMask == 0 ? SpriteScreen.sprReg0Bg0XPort : SpriteScreen.sprReg0Bg0XTest;
  5785:              if (SpriteScreen.sprReg0Bg0XCurr != curr) {
  5786:                SpriteScreen.sprReg0Bg0XCurr = curr;
  5787: /*
  5788:                if (VideoController.vcnReg3Curr << 31 - 6 < 0 &&  //スプライト画面が表示されている
  5789:                    (SpriteScreen.sprReg4BgCtrlCurr & (1 << 9 | 1 << 0)) == (1 << 9 | 1 << 0)) {  //BG0が表示されている
  5790:                  CRTC.crtAllStamp += 2;
  5791:                }
  5792: */
  5793:              }
  5794:            }
  5795:            return;
  5796:          case SpriteScreen.SPR_REG1_BG0_Y:
  5797:            SpriteScreen.sprReg1Bg0YPort = d & 1023;
  5798:            {
  5799:              int curr = SpriteScreen.sprReg1Bg0YMask == 0 ? SpriteScreen.sprReg1Bg0YPort : SpriteScreen.sprReg1Bg0YTest;
  5800:              if (SpriteScreen.sprReg1Bg0YCurr != curr) {
  5801:                SpriteScreen.sprReg1Bg0YCurr = curr;
  5802: /*
  5803:                if (VideoController.vcnReg3Curr << 31 - 6 < 0 &&  //スプライト画面が表示されている
  5804:                    (SpriteScreen.sprReg4BgCtrlCurr & (1 << 9 | 1 << 0)) == (1 << 9 | 1 << 0)) {  //BG0が表示されている
  5805:                  CRTC.crtAllStamp += 2;
  5806:                }
  5807: */
  5808:              }
  5809:            }
  5810:            return;
  5811:          case SpriteScreen.SPR_REG2_BG1_X:
  5812:            SpriteScreen.sprReg2Bg1XPort = d & 1023;
  5813:            {
  5814:              int curr = SpriteScreen.sprReg2Bg1XMask == 0 ? SpriteScreen.sprReg2Bg1XPort : SpriteScreen.sprReg2Bg1XTest;
  5815:              if (SpriteScreen.sprReg2Bg1XCurr != curr) {
  5816:                SpriteScreen.sprReg2Bg1XCurr = curr;
  5817: /*
  5818:                if (VideoController.vcnReg3Curr << 31 - 6 < 0 &&  //スプライト画面が表示されている
  5819:                    (SpriteScreen.sprReg4BgCtrlCurr & (1 << 9 | 1 << 3)) == (1 << 9 | 1 << 3)) {  //BG1が表示されている
  5820:                  CRTC.crtAllStamp += 2;
  5821:                }
  5822: */
  5823:              }
  5824:            }
  5825:            return;
  5826:          case SpriteScreen.SPR_REG3_BG1_Y:
  5827:            SpriteScreen.sprReg3Bg1YPort = d & 1023;
  5828:            {
  5829:              int curr = SpriteScreen.sprReg3Bg1YMask == 0 ? SpriteScreen.sprReg3Bg1YPort : SpriteScreen.sprReg3Bg1YTest;
  5830:              if (SpriteScreen.sprReg3Bg1YCurr != curr) {
  5831:                SpriteScreen.sprReg3Bg1YCurr = curr;
  5832: /*
  5833:                if (VideoController.vcnReg3Curr << 31 - 6 < 0 &&  //スプライト画面が表示されている
  5834:                    (SpriteScreen.sprReg4BgCtrlCurr & (1 << 9 | 1 << 3)) == (1 << 9 | 1 << 3)) {  //BG1が表示されている
  5835:                  CRTC.crtAllStamp += 2;
  5836:                }
  5837: */
  5838:              }
  5839:            }
  5840:            return;
  5841:          case SpriteScreen.SPR_REG4_BG_CTRL:
  5842:            SpriteScreen.sprReg4BgCtrlPort = d & 2047;
  5843:            {
  5844:              int curr = SpriteScreen.sprReg4BgCtrlPort & ~SpriteScreen.sprReg4BgCtrlMask | SpriteScreen.sprReg4BgCtrlTest & SpriteScreen.sprReg4BgCtrlMask;
  5845:              if (SpriteScreen.sprReg4BgCtrlCurr != curr) {
  5846:                SpriteScreen.sprReg4BgCtrlCurr = curr;
  5847: /*
  5848:                if (VideoController.vcnReg3Curr << 31 - 6 < 0) {  //スプライト画面が表示されている
  5849:                  CRTC.crtAllStamp += 2;
  5850:                }
  5851: */
  5852:              }
  5853:            }
  5854:            return;
  5855:          case SpriteScreen.SPR_REG5_H_TOTAL:
  5856:            SpriteScreen.sprReg5HTotalPort = d & 255;
  5857:            {
  5858:              int curr = SpriteScreen.sprReg5HTotalMask == 0 ? SpriteScreen.sprReg5HTotalPort : SpriteScreen.sprReg5HTotalTest;
  5859:              if (SpriteScreen.sprReg5HTotalCurr != curr) {
  5860:                SpriteScreen.sprReg5HTotalCurr = curr;
  5861: /*
  5862:                if (VideoController.vcnReg3Curr << 31 - 6 < 0 &&  //スプライト画面が表示されている
  5863:                    SpriteScreen.sprReg4BgCtrlCurr << 31 - 9 < 0) {  //スプライト画面が表示されている
  5864:                  CRTC.crtAllStamp += 2;
  5865:                }
  5866: */
  5867:              }
  5868:            }
  5869:            return;
  5870:          case SpriteScreen.SPR_REG6_H_START:
  5871:            SpriteScreen.sprReg6HStartPort = d & 63;
  5872:            {
  5873:              int curr = SpriteScreen.sprReg6HStartMask == 0 ? SpriteScreen.sprReg6HStartPort : SpriteScreen.sprReg6HStartTest;
  5874:              if (SpriteScreen.sprReg6HStartCurr != curr) {
  5875:                SpriteScreen.sprReg6HStartCurr = curr;
  5876: /*
  5877:                if (VideoController.vcnReg3Curr << 31 - 6 < 0 &&  //スプライト画面が表示されている
  5878:                    SpriteScreen.sprReg4BgCtrlCurr << 31 - 9 < 0) {  //スプライト画面が表示されている
  5879:                  CRTC.crtAllStamp += 2;
  5880:                }
  5881: */
  5882:              }
  5883:            }
  5884:            return;
  5885:          case SpriteScreen.SPR_REG7_V_START:
  5886:            SpriteScreen.sprReg7VStartPort = d & 255;
  5887:            {
  5888:              int curr = SpriteScreen.sprReg7VStartMask == 0 ? SpriteScreen.sprReg7VStartPort : SpriteScreen.sprReg7VStartTest;
  5889:              if (SpriteScreen.sprReg7VStartCurr != curr) {
  5890:                SpriteScreen.sprReg7VStartCurr = curr;
  5891: /*
  5892:                if (VideoController.vcnReg3Curr << 31 - 6 < 0 &&  //スプライト画面が表示されている
  5893:                    SpriteScreen.sprReg4BgCtrlCurr << 31 - 9 < 0) {  //スプライト画面が表示されている
  5894:                  CRTC.crtAllStamp += 2;
  5895:                }
  5896: */
  5897:              }
  5898:            }
  5899:            return;
  5900:          case SpriteScreen.SPR_REG8_RESO:
  5901:            SpriteScreen.sprReg8ResoPort = d & 31;
  5902:            {
  5903:              int curr = SpriteScreen.sprReg8ResoPort & ~SpriteScreen.sprReg8ResoMask | SpriteScreen.sprReg8ResoTest & SpriteScreen.sprReg8ResoMask;
  5904:              if (SpriteScreen.sprReg8ResoCurr != curr) {
  5905:                SpriteScreen.sprReg8ResoCurr = curr;
  5906: /*
  5907:                if (VideoController.vcnReg3Curr << 31 - 6 < 0 &&  //スプライト画面が表示されている
  5908:                    SpriteScreen.sprReg4BgCtrlCurr << 31 - 9 < 0) {  //スプライト画面が表示されている
  5909:                  CRTC.crtAllStamp += 2;
  5910:                }
  5911: */
  5912:              }
  5913:            }
  5914:            return;
  5915:          }
  5916:          return;
  5917:        } else {  //PCGエリアとテキストエリア
  5918:          if (a >= 0x00ebe000) {  //テキストエリア1
  5919:            int n = a >> 1 & 0x0fff;
  5920:            SpriteScreen.sprT1Num[n] = (short) ((d & 0x00ff) << 3);
  5921:            SpriteScreen.sprT1ColPort[n] = (short) ((d & 0x0f00) >> 4);
  5922:            SpriteScreen.sprT1H[n] = (short) (d << 1) < 0;
  5923:            SpriteScreen.sprT1V[n] = (short) d < 0;
  5924: /*
  5925:            if (VideoController.vcnReg3Curr << 31 - 6 < 0 &&  //スプライト画面が表示されている
  5926:                SpriteScreen.sprReg4BgCtrlCurr << 31 - 9 < 0) {  //スプライト画面が表示されている
  5927:              if ((SpriteScreen.sprReg4BgCtrlCurr & 0b111) == 0b011) {  //BG0が表示されていてBG0にTEXT1が割り当てられている
  5928:                if ((SpriteScreen.sprReg8ResoCurr & 0x0003) == 0) {  //水平256ドット→8x8
  5929:                  int y = (n >> 6 << 3) - SpriteScreen.sprReg1Bg0YCurr;
  5930:                  CRTC.crtRasterStamp[y     & 511] = 0;
  5931:                  CRTC.crtRasterStamp[y + 1 & 511] = 0;
  5932:                  CRTC.crtRasterStamp[y + 2 & 511] = 0;
  5933:                  CRTC.crtRasterStamp[y + 3 & 511] = 0;
  5934:                  CRTC.crtRasterStamp[y + 4 & 511] = 0;
  5935:                  CRTC.crtRasterStamp[y + 5 & 511] = 0;
  5936:                  CRTC.crtRasterStamp[y + 6 & 511] = 0;
  5937:                  CRTC.crtRasterStamp[y + 7 & 511] = 0;
  5938:                } else {  //水平512ドット→16x16
  5939:                  int y = (n >> 6 << 4) - SpriteScreen.sprReg1Bg0YCurr;
  5940:                  CRTC.crtRasterStamp[y      & 1023] = 0;
  5941:                  CRTC.crtRasterStamp[y +  1 & 1023] = 0;
  5942:                  CRTC.crtRasterStamp[y +  2 & 1023] = 0;
  5943:                  CRTC.crtRasterStamp[y +  3 & 1023] = 0;
  5944:                  CRTC.crtRasterStamp[y +  4 & 1023] = 0;
  5945:                  CRTC.crtRasterStamp[y +  5 & 1023] = 0;
  5946:                  CRTC.crtRasterStamp[y +  6 & 1023] = 0;
  5947:                  CRTC.crtRasterStamp[y +  7 & 1023] = 0;
  5948:                  CRTC.crtRasterStamp[y +  8 & 1023] = 0;
  5949:                  CRTC.crtRasterStamp[y +  9 & 1023] = 0;
  5950:                  CRTC.crtRasterStamp[y + 10 & 1023] = 0;
  5951:                  CRTC.crtRasterStamp[y + 11 & 1023] = 0;
  5952:                  CRTC.crtRasterStamp[y + 12 & 1023] = 0;
  5953:                  CRTC.crtRasterStamp[y + 13 & 1023] = 0;
  5954:                  CRTC.crtRasterStamp[y + 14 & 1023] = 0;
  5955:                  CRTC.crtRasterStamp[y + 15 & 1023] = 0;
  5956:                }
  5957:              }
  5958:              if ((SpriteScreen.sprReg4BgCtrlCurr & 0b111_000) == 0b011_000) {  //BG1が表示されていてBG1にTEXT1が割り当てられている
  5959:                int y = (n >> 6 << 3) - SpriteScreen.sprReg3Bg1YCurr;
  5960:                CRTC.crtRasterStamp[y     & 511] = 0;
  5961:                CRTC.crtRasterStamp[y + 1 & 511] = 0;
  5962:                CRTC.crtRasterStamp[y + 2 & 511] = 0;
  5963:                CRTC.crtRasterStamp[y + 3 & 511] = 0;
  5964:                CRTC.crtRasterStamp[y + 4 & 511] = 0;
  5965:                CRTC.crtRasterStamp[y + 5 & 511] = 0;
  5966:                CRTC.crtRasterStamp[y + 6 & 511] = 0;
  5967:                CRTC.crtRasterStamp[y + 7 & 511] = 0;
  5968:              }
  5969:            }
  5970: */
  5971:          } else if (a >= 0x00ebc000) {  //テキストエリア0
  5972:            int n = a >> 1 & 0x0fff;
  5973:            SpriteScreen.sprT0Num[n] = (short) ((d & 0x00ff) << 3);
  5974:            SpriteScreen.sprT0ColPort[n] = (short) ((d & 0x0f00) >> 4);
  5975:            SpriteScreen.sprT0H[n] = (short) (d << 1) < 0;
  5976:            SpriteScreen.sprT0V[n] = (short) d < 0;
  5977: /*
  5978:            if (VideoController.vcnReg3Curr << 31 - 6 < 0 &&  //スプライト画面が表示されている
  5979:                SpriteScreen.sprReg4BgCtrlCurr << 31 - 9 < 0) {  //スプライト画面が表示されている
  5980:              if ((SpriteScreen.sprReg4BgCtrlCurr & 0b111) == 0b001) {  //BG0が表示されていてBG0にTEXT0が割り当てられている
  5981:                if ((SpriteScreen.sprReg8ResoCurr & 0x0003) == 0) {  //水平256ドット→8x8
  5982:                  int y = (n >> 6 << 3) - SpriteScreen.sprReg1Bg0YCurr;
  5983:                  CRTC.crtRasterStamp[y     & 511] = 0;
  5984:                  CRTC.crtRasterStamp[y + 1 & 511] = 0;
  5985:                  CRTC.crtRasterStamp[y + 2 & 511] = 0;
  5986:                  CRTC.crtRasterStamp[y + 3 & 511] = 0;
  5987:                  CRTC.crtRasterStamp[y + 4 & 511] = 0;
  5988:                  CRTC.crtRasterStamp[y + 5 & 511] = 0;
  5989:                  CRTC.crtRasterStamp[y + 6 & 511] = 0;
  5990:                  CRTC.crtRasterStamp[y + 7 & 511] = 0;
  5991:                } else {  //水平512ドット→16x16
  5992:                  int y = (n >> 6 << 4) - SpriteScreen.sprReg1Bg0YCurr;
  5993:                  CRTC.crtRasterStamp[y      & 1023] = 0;
  5994:                  CRTC.crtRasterStamp[y +  1 & 1023] = 0;
  5995:                  CRTC.crtRasterStamp[y +  2 & 1023] = 0;
  5996:                  CRTC.crtRasterStamp[y +  3 & 1023] = 0;
  5997:                  CRTC.crtRasterStamp[y +  4 & 1023] = 0;
  5998:                  CRTC.crtRasterStamp[y +  5 & 1023] = 0;
  5999:                  CRTC.crtRasterStamp[y +  6 & 1023] = 0;
  6000:                  CRTC.crtRasterStamp[y +  7 & 1023] = 0;
  6001:                  CRTC.crtRasterStamp[y +  8 & 1023] = 0;
  6002:                  CRTC.crtRasterStamp[y +  9 & 1023] = 0;
  6003:                  CRTC.crtRasterStamp[y + 10 & 1023] = 0;
  6004:                  CRTC.crtRasterStamp[y + 11 & 1023] = 0;
  6005:                  CRTC.crtRasterStamp[y + 12 & 1023] = 0;
  6006:                  CRTC.crtRasterStamp[y + 13 & 1023] = 0;
  6007:                  CRTC.crtRasterStamp[y + 14 & 1023] = 0;
  6008:                  CRTC.crtRasterStamp[y + 15 & 1023] = 0;
  6009:                }
  6010:              }
  6011:              if ((SpriteScreen.sprReg4BgCtrlCurr & 0b111_000) == 0b001_000) {  //BG1が表示されていてBG1にTEXT0が割り当てられている
  6012:                int y = (n >> 6 << 3) - SpriteScreen.sprReg3Bg1YCurr;
  6013:                CRTC.crtRasterStamp[y     & 511] = 0;
  6014:                CRTC.crtRasterStamp[y + 1 & 511] = 0;
  6015:                CRTC.crtRasterStamp[y + 2 & 511] = 0;
  6016:                CRTC.crtRasterStamp[y + 3 & 511] = 0;
  6017:                CRTC.crtRasterStamp[y + 4 & 511] = 0;
  6018:                CRTC.crtRasterStamp[y + 5 & 511] = 0;
  6019:                CRTC.crtRasterStamp[y + 6 & 511] = 0;
  6020:                CRTC.crtRasterStamp[y + 7 & 511] = 0;
  6021:              }
  6022:            }
  6023: */
  6024:          }
  6025:          int t = a >> 2 & 0x1fff;
  6026:          SpriteScreen.sprPatPort[t] = (a & 0x02) == 0 ? d << 16 | (char) SpriteScreen.sprPatPort[t] : ~0xffff & SpriteScreen.sprPatPort[t] | (char) d;
  6027: /*
  6028:          if (VideoController.vcnReg3Curr << 31 - 6 < 0 &&  //スプライト画面が表示されている
  6029:              SpriteScreen.sprReg4BgCtrlCurr << 31 - 9 < 0) {  //スプライト画面が表示されている
  6030:            int num = a >> 7 & 255;  //num=パターン番号
  6031:            if (SpriteScreen.SPR_RRMAP) {
  6032:              for (int i = num << 2, nn = 0; nn <= 128 - 32; nn += 32) {
  6033:                for (int map = SpriteScreen.sprPPmap[i++], n = nn; map != 0; map <<= 1, n++) {
  6034:                  if (map >= 0) {  //このスプライトには割り当てられていない
  6035:                    continue;
  6036:                  }
  6037:                  int y = SpriteScreen.sprY[n];
  6038:                  if (true) {
  6039:                    if (y < 16) {
  6040:                      for (int k = 0; k < y; k++) {
  6041:                        CRTC.crtRasterStamp[k] = 0;
  6042:                      }
  6043:                    } else {
  6044:                      CRTC.crtRasterStamp[y - 16] = 0;
  6045:                      CRTC.crtRasterStamp[y - 15] = 0;
  6046:                      CRTC.crtRasterStamp[y - 14] = 0;
  6047:                      CRTC.crtRasterStamp[y - 13] = 0;
  6048:                      CRTC.crtRasterStamp[y - 12] = 0;
  6049:                      CRTC.crtRasterStamp[y - 11] = 0;
  6050:                      CRTC.crtRasterStamp[y - 10] = 0;
  6051:                      CRTC.crtRasterStamp[y -  9] = 0;
  6052:                      CRTC.crtRasterStamp[y -  8] = 0;
  6053:                      CRTC.crtRasterStamp[y -  7] = 0;
  6054:                      CRTC.crtRasterStamp[y -  6] = 0;
  6055:                      CRTC.crtRasterStamp[y -  5] = 0;
  6056:                      CRTC.crtRasterStamp[y -  4] = 0;
  6057:                      CRTC.crtRasterStamp[y -  3] = 0;
  6058:                      CRTC.crtRasterStamp[y -  2] = 0;
  6059:                      CRTC.crtRasterStamp[y -  1] = 0;
  6060:                    }
  6061:                  } else {
  6062:                    Arrays.fill (CRTC.crtRasterStamp, y < 16 ? 0 : y - 16, y, 0);
  6063:                  }
  6064:                }  //for map,n
  6065:              }  //for i,nn
  6066:            } else {  //!SpriteScreen.SPR_RRMAP
  6067:              for (int i = 96; i >= 0; i -= 32) {
  6068:                int map = SpriteScreen.sprPmap[i >> 5][num];
  6069:                if (map == 0) {
  6070:                  continue;
  6071:                }
  6072:                for (int n = i + 31; n >= i; n--) {  //n=スプライト番号
  6073:                  if (map < 0) {
  6074:                    int y = SpriteScreen.sprY[n];
  6075:                    if (true) {
  6076:                      if (y < 16) {
  6077:                        for (int k = 0; k < y; k++) {
  6078:                          CRTC.crtRasterStamp[k] = 0;
  6079:                        }
  6080:                      } else {
  6081:                        CRTC.crtRasterStamp[y - 16] = 0;
  6082:                        CRTC.crtRasterStamp[y - 15] = 0;
  6083:                        CRTC.crtRasterStamp[y - 14] = 0;
  6084:                        CRTC.crtRasterStamp[y - 13] = 0;
  6085:                        CRTC.crtRasterStamp[y - 12] = 0;
  6086:                        CRTC.crtRasterStamp[y - 11] = 0;
  6087:                        CRTC.crtRasterStamp[y - 10] = 0;
  6088:                        CRTC.crtRasterStamp[y -  9] = 0;
  6089:                        CRTC.crtRasterStamp[y -  8] = 0;
  6090:                        CRTC.crtRasterStamp[y -  7] = 0;
  6091:                        CRTC.crtRasterStamp[y -  6] = 0;
  6092:                        CRTC.crtRasterStamp[y -  5] = 0;
  6093:                        CRTC.crtRasterStamp[y -  4] = 0;
  6094:                        CRTC.crtRasterStamp[y -  3] = 0;
  6095:                        CRTC.crtRasterStamp[y -  2] = 0;
  6096:                        CRTC.crtRasterStamp[y -  1] = 0;
  6097:                      }
  6098:                    } else {
  6099:                      Arrays.fill (CRTC.crtRasterStamp, y < 16 ? 0 : y - 16, y, 0);
  6100:                    }
  6101:                  }  //if map<0
  6102:                  map <<= 1;
  6103:                }  //for n
  6104:              }  //for i
  6105:            }  //if SpriteScreen.SPR_RRMAP/!SpriteScreen.SPR_RRMAP
  6106:          }  //(VideoController.vcnReg3Curr&0x40)!=0
  6107: */
  6108:        }  //PCGエリアとテキストエリア
  6109:      }  //mmdWw
  6110:     @Override protected void mmdWl (int a, int d) throws M68kException {
  6111:        a &= XEiJ.BUS_MOTHER_MASK;
  6112:        mmdWw (a    , d >> 16);
  6113:        mmdWw (a + 2, d      );
  6114:      }
  6115:   },  //MMD_SPR
  6116: 
  6117:   //--------------------------------------------------------------------------------
  6118:   //MMD_SMR SRAM
  6119:   MMD_SMR {
  6120:     @Override public String toString () {
  6121:       return Multilingual.mlnJapanese ? "SRAM" : "SRAM";
  6122:     }
  6123:     //ピーク
  6124:     @Override protected byte mmdPbs (int a) {
  6125:       a &= XEiJ.BUS_MOTHER_MASK;
  6126:       return MainMemory.mmrM8[a];
  6127:     }
  6128:     @Override protected int mmdPbz (int a) {
  6129:       a &= XEiJ.BUS_MOTHER_MASK;
  6130:       return MainMemory.mmrM8[a] & 255;
  6131:     }
  6132:     @Override protected int mmdPws (int a) {
  6133:       a &= XEiJ.BUS_MOTHER_MASK;
  6134:       if (MainMemory.MMR_USE_BYTE_BUFFER) {
  6135:         return MainMemory.mmrBuffer.getShort (a);
  6136:       } else {
  6137:         return MainMemory.mmrM8[a] << 8 | MainMemory.mmrM8[a + 1] & 255;
  6138:       }
  6139:     }
  6140:     @Override protected int mmdPwz (int a) {
  6141:       a &= XEiJ.BUS_MOTHER_MASK;
  6142:       if (MainMemory.MMR_USE_BYTE_BUFFER) {
  6143:         return MainMemory.mmrBuffer.getChar (a);
  6144:       } else {
  6145:         return (char) (MainMemory.mmrM8[a] << 8 | MainMemory.mmrM8[a + 1] & 255);
  6146:       }
  6147:     }
  6148:     @Override protected int mmdPls (int a) {
  6149:       a &= XEiJ.BUS_MOTHER_MASK;
  6150:       if (MainMemory.MMR_USE_BYTE_BUFFER) {
  6151:         return MainMemory.mmrBuffer.getInt (a);
  6152:       } else {
  6153:         return MainMemory.mmrM8[a] << 24 | (MainMemory.mmrM8[a + 1] & 255) << 16 | (char) (MainMemory.mmrM8[a + 2] << 8 | MainMemory.mmrM8[a + 3] & 255);
  6154:       }
  6155:     }
  6156:     //リード
  6157:     @Override protected byte mmdRbs (int a) throws M68kException {
  6158:        a &= XEiJ.BUS_MOTHER_MASK;
  6159:        return MainMemory.mmrM8[a];
  6160:      }
  6161:     @Override protected int mmdRbz (int a) throws M68kException {
  6162:        a &= XEiJ.BUS_MOTHER_MASK;
  6163:        return MainMemory.mmrM8[a] & 255;
  6164:      }
  6165:     @Override protected int mmdRws (int a) throws M68kException {
  6166:        a &= XEiJ.BUS_MOTHER_MASK;
  6167:        if (a == 0x00ed0018 &&  //起動デバイス
  6168:            XEiJ.mpuBootDevice >= 0 &&  //「ここから再起動」
  6169:            XEiJ.regPC0 == XEiJ.romBootDeviceRead) {  //起動デバイス
  6170:          return (short) XEiJ.mpuBootDevice;
  6171:        }
  6172:        if (MainMemory.MMR_USE_BYTE_BUFFER) {
  6173:          return MainMemory.mmrBuffer.getShort (a);
  6174:        } else {
  6175:          return MainMemory.mmrM8[a] << 8 | MainMemory.mmrM8[a + 1] & 255;
  6176:        }
  6177:      }
  6178:     @Override protected int mmdRwz (int a) throws M68kException {
  6179:        a &= XEiJ.BUS_MOTHER_MASK;
  6180:        if (a == 0x00ed0018 &&  //起動デバイス
  6181:            XEiJ.mpuBootDevice >= 0 &&  //「ここから再起動」
  6182:            XEiJ.regPC0 == XEiJ.romBootDeviceRead) {  //起動デバイス
  6183:          return XEiJ.mpuBootDevice;
  6184:        }
  6185:        if (MainMemory.MMR_USE_BYTE_BUFFER) {
  6186:          return MainMemory.mmrBuffer.getChar (a);
  6187:        } else {
  6188:          return (char) (MainMemory.mmrM8[a] << 8 | MainMemory.mmrM8[a + 1] & 255);
  6189:        }
  6190:      }
  6191:     @Override protected int mmdRls (int a) throws M68kException {
  6192:        a &= XEiJ.BUS_MOTHER_MASK;
  6193:        if (a == 0x00ed000c) {  //ROM起動ハンドル
  6194:          if (XEiJ.mpuBootDevice == 0xa000) {  //「ここから再起動」でROM起動
  6195:            if (XEiJ.regPC0 == XEiJ.romBootROMAddressRead ||  //起動シーケンス
  6196:                XEiJ.regPC0 == XEiJ.romBootinfROMAddressRead) {  //IOCS _BOOTINF
  6197:              return XEiJ.mpuBootAddress;
  6198:            }
  6199:          }
  6200:        } else if (a == 0x00ed0010) {  //RAM起動アドレス
  6201:          if (XEiJ.mpuBootDevice == 0xb000) {  //「ここから再起動」でRAM起動
  6202:            if (XEiJ.regPC0 == XEiJ.romBootRAMAddressRead ||  //起動シーケンス
  6203:                XEiJ.regPC0 == XEiJ.romBootinfRAMAddressRead) {  //IOCS _BOOTINF
  6204:              return XEiJ.mpuBootAddress;
  6205:            }
  6206:          }
  6207:        }
  6208:        if (MainMemory.MMR_USE_BYTE_BUFFER) {
  6209:          return MainMemory.mmrBuffer.getInt (a);
  6210:        } else {
  6211:          return MainMemory.mmrM8[a] << 24 | (MainMemory.mmrM8[a + 1] & 255) << 16 | (char) (MainMemory.mmrM8[a + 2] << 8 | MainMemory.mmrM8[a + 3] & 255);
  6212:        }
  6213:      }
  6214:     //ライト
  6215:     @Override protected void mmdWb (int a, int d) throws M68kException {
  6216:        a &= XEiJ.BUS_MOTHER_MASK;
  6217:        if (XEiJ.smrWriteEnableOn) {
  6218:          MainMemory.mmrM8[a] = (byte) d;
  6219:          if (a == 0x00ed002b || a == 0x00ed0059) {  //キーボードの配列または字体が変化した
  6220:            Keyboard.kbdRepaint ();  //キーボードが表示されているときkbdImageを作り直して再描画する
  6221:          }
  6222:          return;
  6223:        }
  6224:        super.mmdWb (a, d);  //バスエラー
  6225:      }
  6226:     @Override protected void mmdWw (int a, int d) throws M68kException {
  6227:        a &= XEiJ.BUS_MOTHER_MASK;
  6228:        mmdWb (a    , d >> 8);
  6229:        mmdWb (a + 1, d     );
  6230:      }
  6231:     @Override protected void mmdWl (int a, int d) throws M68kException {
  6232:        a &= XEiJ.BUS_MOTHER_MASK;
  6233:        mmdWw (a    , d >> 16);
  6234:        mmdWw (a + 2, d      );
  6235:      }
  6236:   },  //MMD_SMR
  6237: 
  6238:   //--------------------------------------------------------------------------------
  6239:   //MMD_CG1 CGROM1
  6240:   MMD_CG1 {
  6241:     @Override public String toString () {
  6242:       return Multilingual.mlnJapanese ? "CGROM" : "CGROM";
  6243:     }
  6244:     //ピーク
  6245:     @Override protected byte mmdPbs (int a) {
  6246:       a &= XEiJ.BUS_MOTHER_MASK;
  6247:       if (FontEditor.FNT_CREATE_CGROM_LATER) {
  6248:         FontEditor.fntCreateCG1 ();
  6249:       }
  6250:       return MainMemory.mmrM8[a];
  6251:     }
  6252:     @Override protected int mmdPbz (int a) {
  6253:       a &= XEiJ.BUS_MOTHER_MASK;
  6254:       if (FontEditor.FNT_CREATE_CGROM_LATER) {
  6255:         FontEditor.fntCreateCG1 ();
  6256:       }
  6257:       return MainMemory.mmrM8[a] & 255;
  6258:     }
  6259:     @Override protected int mmdPws (int a) {
  6260:       a &= XEiJ.BUS_MOTHER_MASK;
  6261:       if (FontEditor.FNT_CREATE_CGROM_LATER) {
  6262:         FontEditor.fntCreateCG1 ();
  6263:       }
  6264:       if (MainMemory.MMR_USE_BYTE_BUFFER) {
  6265:         return MainMemory.mmrBuffer.getShort (a);
  6266:       } else {
  6267:         return MainMemory.mmrM8[a] << 8 | MainMemory.mmrM8[a + 1] & 255;
  6268:       }
  6269:     }
  6270:     @Override protected int mmdPwz (int a) {
  6271:       a &= XEiJ.BUS_MOTHER_MASK;
  6272:       if (FontEditor.FNT_CREATE_CGROM_LATER) {
  6273:         FontEditor.fntCreateCG1 ();
  6274:       }
  6275:       if (MainMemory.MMR_USE_BYTE_BUFFER) {
  6276:         return MainMemory.mmrBuffer.getChar (a);
  6277:       } else {
  6278:         return (char) (MainMemory.mmrM8[a] << 8 | MainMemory.mmrM8[a + 1] & 255);
  6279:       }
  6280:     }
  6281:     @Override protected int mmdPls (int a) {
  6282:       a &= XEiJ.BUS_MOTHER_MASK;
  6283:       if (FontEditor.FNT_CREATE_CGROM_LATER) {
  6284:         FontEditor.fntCreateCG1 ();
  6285:       }
  6286:       if (MainMemory.MMR_USE_BYTE_BUFFER) {
  6287:         return MainMemory.mmrBuffer.getInt (a);
  6288:       } else {
  6289:         return MainMemory.mmrM8[a] << 24 | (MainMemory.mmrM8[a + 1] & 255) << 16 | (char) (MainMemory.mmrM8[a + 2] << 8 | MainMemory.mmrM8[a + 3] & 255);
  6290:       }
  6291:     }
  6292:     //リード
  6293:     @Override protected byte mmdRbs (int a) throws M68kException {
  6294:        a &= XEiJ.BUS_MOTHER_MASK;
  6295:        if (FontEditor.FNT_CREATE_CGROM_LATER) {
  6296:          FontEditor.fntCreateCG1 ();
  6297:        }
  6298:        XEiJ.mpuCycleCount += XEiJ.mpuRomWait;
  6299:        return MainMemory.mmrM8[a];
  6300:      }
  6301:     @Override protected int mmdRbz (int a) throws M68kException {
  6302:        a &= XEiJ.BUS_MOTHER_MASK;
  6303:        if (FontEditor.FNT_CREATE_CGROM_LATER) {
  6304:          FontEditor.fntCreateCG1 ();
  6305:        }
  6306:        XEiJ.mpuCycleCount += XEiJ.mpuRomWait;
  6307:        return MainMemory.mmrM8[a] & 255;
  6308:      }
  6309:     @Override protected int mmdRws (int a) throws M68kException {
  6310:        a &= XEiJ.BUS_MOTHER_MASK;
  6311:        if (FontEditor.FNT_CREATE_CGROM_LATER) {
  6312:          FontEditor.fntCreateCG1 ();
  6313:        }
  6314:        XEiJ.mpuCycleCount += XEiJ.mpuRomWait;
  6315:        if (MainMemory.MMR_USE_BYTE_BUFFER) {
  6316:          return MainMemory.mmrBuffer.getShort (a);
  6317:        } else {
  6318:          return MainMemory.mmrM8[a] << 8 | MainMemory.mmrM8[a + 1] & 255;
  6319:        }
  6320:      }
  6321:     @Override protected int mmdRwz (int a) throws M68kException {
  6322:        a &= XEiJ.BUS_MOTHER_MASK;
  6323:        if (FontEditor.FNT_CREATE_CGROM_LATER) {
  6324:          FontEditor.fntCreateCG1 ();
  6325:        }
  6326:        XEiJ.mpuCycleCount += XEiJ.mpuRomWait;
  6327:        if (MainMemory.MMR_USE_BYTE_BUFFER) {
  6328:          return MainMemory.mmrBuffer.getChar (a);
  6329:        } else {
  6330:          return (char) (MainMemory.mmrM8[a] << 8 | MainMemory.mmrM8[a + 1] & 255);
  6331:        }
  6332:      }
  6333:     @Override protected int mmdRls (int a) throws M68kException {
  6334:        a &= XEiJ.BUS_MOTHER_MASK;
  6335:        if (FontEditor.FNT_CREATE_CGROM_LATER) {
  6336:          FontEditor.fntCreateCG1 ();
  6337:        }
  6338:        XEiJ.mpuCycleCount += XEiJ.mpuRomWait << 1;
  6339:        if (MainMemory.MMR_USE_BYTE_BUFFER) {
  6340:          return MainMemory.mmrBuffer.getInt (a);
  6341:        } else {
  6342:          return MainMemory.mmrM8[a] << 24 | (MainMemory.mmrM8[a + 1] & 255) << 16 | (char) (MainMemory.mmrM8[a + 2] << 8 | MainMemory.mmrM8[a + 3] & 255);
  6343:        }
  6344:      }
  6345:   },  //MMD_CG1
  6346: 
  6347:   //--------------------------------------------------------------------------------
  6348:   //MMD_CG2 CGROM2
  6349:   MMD_CG2 {
  6350:     @Override public String toString () {
  6351:       return Multilingual.mlnJapanese ? "CGROM" : "CGROM";
  6352:     }
  6353:     //ピーク
  6354:     @Override protected byte mmdPbs (int a) {
  6355:       a &= XEiJ.BUS_MOTHER_MASK;
  6356:       if (FontEditor.FNT_CREATE_CGROM_LATER) {
  6357:         FontEditor.fntCreateCG2 ();
  6358:       }
  6359:       return MainMemory.mmrM8[a];
  6360:     }
  6361:     @Override protected int mmdPbz (int a) {
  6362:       a &= XEiJ.BUS_MOTHER_MASK;
  6363:       if (FontEditor.FNT_CREATE_CGROM_LATER) {
  6364:         FontEditor.fntCreateCG2 ();
  6365:       }
  6366:       return MainMemory.mmrM8[a] & 255;
  6367:     }
  6368:     @Override protected int mmdPws (int a) {
  6369:       a &= XEiJ.BUS_MOTHER_MASK;
  6370:       if (FontEditor.FNT_CREATE_CGROM_LATER) {
  6371:         FontEditor.fntCreateCG2 ();
  6372:       }
  6373:       if (MainMemory.MMR_USE_BYTE_BUFFER) {
  6374:         return MainMemory.mmrBuffer.getShort (a);
  6375:       } else {
  6376:         return MainMemory.mmrM8[a] << 8 | MainMemory.mmrM8[a + 1] & 255;
  6377:       }
  6378:     }
  6379:     @Override protected int mmdPwz (int a) {
  6380:       a &= XEiJ.BUS_MOTHER_MASK;
  6381:       if (FontEditor.FNT_CREATE_CGROM_LATER) {
  6382:         FontEditor.fntCreateCG2 ();
  6383:       }
  6384:       if (MainMemory.MMR_USE_BYTE_BUFFER) {
  6385:         return MainMemory.mmrBuffer.getChar (a);
  6386:       } else {
  6387:         return (char) (MainMemory.mmrM8[a] << 8 | MainMemory.mmrM8[a + 1] & 255);
  6388:       }
  6389:     }
  6390:     @Override protected int mmdPls (int a) {
  6391:       a &= XEiJ.BUS_MOTHER_MASK;
  6392:       if (FontEditor.FNT_CREATE_CGROM_LATER) {
  6393:         FontEditor.fntCreateCG2 ();
  6394:       }
  6395:       if (MainMemory.MMR_USE_BYTE_BUFFER) {
  6396:         return MainMemory.mmrBuffer.getInt (a);
  6397:       } else {
  6398:         return MainMemory.mmrM8[a] << 24 | (MainMemory.mmrM8[a + 1] & 255) << 16 | (char) (MainMemory.mmrM8[a + 2] << 8 | MainMemory.mmrM8[a + 3] & 255);
  6399:       }
  6400:     }
  6401:     //リード
  6402:     @Override protected byte mmdRbs (int a) throws M68kException {
  6403:        a &= XEiJ.BUS_MOTHER_MASK;
  6404:        if (FontEditor.FNT_CREATE_CGROM_LATER) {
  6405:          FontEditor.fntCreateCG2 ();
  6406:        }
  6407:        XEiJ.mpuCycleCount += XEiJ.mpuRomWait;
  6408:        return MainMemory.mmrM8[a];
  6409:      }
  6410:     @Override protected int mmdRbz (int a) throws M68kException {
  6411:        a &= XEiJ.BUS_MOTHER_MASK;
  6412:        if (FontEditor.FNT_CREATE_CGROM_LATER) {
  6413:          FontEditor.fntCreateCG2 ();
  6414:        }
  6415:        XEiJ.mpuCycleCount += XEiJ.mpuRomWait;
  6416:        return MainMemory.mmrM8[a] & 255;
  6417:      }
  6418:     @Override protected int mmdRws (int a) throws M68kException {
  6419:        a &= XEiJ.BUS_MOTHER_MASK;
  6420:        if (FontEditor.FNT_CREATE_CGROM_LATER) {
  6421:          FontEditor.fntCreateCG2 ();
  6422:        }
  6423:        XEiJ.mpuCycleCount += XEiJ.mpuRomWait;
  6424:        if (MainMemory.MMR_USE_BYTE_BUFFER) {
  6425:          return MainMemory.mmrBuffer.getShort (a);
  6426:        } else {
  6427:          return MainMemory.mmrM8[a] << 8 | MainMemory.mmrM8[a + 1] & 255;
  6428:        }
  6429:      }
  6430:     @Override protected int mmdRwz (int a) throws M68kException {
  6431:        a &= XEiJ.BUS_MOTHER_MASK;
  6432:        if (FontEditor.FNT_CREATE_CGROM_LATER) {
  6433:          FontEditor.fntCreateCG2 ();
  6434:        }
  6435:        XEiJ.mpuCycleCount += XEiJ.mpuRomWait;
  6436:        if (MainMemory.MMR_USE_BYTE_BUFFER) {
  6437:          return MainMemory.mmrBuffer.getChar (a);
  6438:        } else {
  6439:          return (char) (MainMemory.mmrM8[a] << 8 | MainMemory.mmrM8[a + 1] & 255);
  6440:        }
  6441:      }
  6442:     @Override protected int mmdRls (int a) throws M68kException {
  6443:        a &= XEiJ.BUS_MOTHER_MASK;
  6444:        if (FontEditor.FNT_CREATE_CGROM_LATER) {
  6445:          FontEditor.fntCreateCG2 ();
  6446:        }
  6447:        XEiJ.mpuCycleCount += XEiJ.mpuRomWait << 1;
  6448:        if (MainMemory.MMR_USE_BYTE_BUFFER) {
  6449:          return MainMemory.mmrBuffer.getInt (a);
  6450:        } else {
  6451:          return MainMemory.mmrM8[a] << 24 | (MainMemory.mmrM8[a + 1] & 255) << 16 | (char) (MainMemory.mmrM8[a + 2] << 8 | MainMemory.mmrM8[a + 3] & 255);
  6452:        }
  6453:      }
  6454:   },  //MMD_CG2
  6455: 
  6456:   //--------------------------------------------------------------------------------
  6457:   //MMD_ROM ROM
  6458:   MMD_ROM {
  6459:     @Override public String toString () {
  6460:       return Multilingual.mlnJapanese ? "ROM" : "ROM";
  6461:     }
  6462:     //ピーク
  6463:     @Override protected byte mmdPbs (int a) {
  6464:       a &= XEiJ.BUS_MOTHER_MASK;
  6465:       return MainMemory.mmrM8[a];
  6466:     }
  6467:     @Override protected int mmdPbz (int a) {
  6468:       a &= XEiJ.BUS_MOTHER_MASK;
  6469:       return MainMemory.mmrM8[a] & 255;
  6470:     }
  6471:     @Override protected int mmdPws (int a) {
  6472:       a &= XEiJ.BUS_MOTHER_MASK;
  6473:       if (MainMemory.MMR_USE_BYTE_BUFFER) {
  6474:         return MainMemory.mmrBuffer.getShort (a);
  6475:       } else {
  6476:         return MainMemory.mmrM8[a] << 8 | MainMemory.mmrM8[a + 1] & 255;
  6477:       }
  6478:     }
  6479:     @Override protected int mmdPwz (int a) {
  6480:       a &= XEiJ.BUS_MOTHER_MASK;
  6481:       if (MainMemory.MMR_USE_BYTE_BUFFER) {
  6482:         return MainMemory.mmrBuffer.getChar (a);
  6483:       } else {
  6484:         return (char) (MainMemory.mmrM8[a] << 8 | MainMemory.mmrM8[a + 1] & 255);
  6485:       }
  6486:     }
  6487:     @Override protected int mmdPls (int a) {
  6488:       a &= XEiJ.BUS_MOTHER_MASK;
  6489:       if (MainMemory.MMR_USE_BYTE_BUFFER) {
  6490:         return MainMemory.mmrBuffer.getInt (a);
  6491:       } else {
  6492:         return MainMemory.mmrM8[a] << 24 | (MainMemory.mmrM8[a + 1] & 255) << 16 | (char) (MainMemory.mmrM8[a + 2] << 8 | MainMemory.mmrM8[a + 3] & 255);
  6493:       }
  6494:     }
  6495:     //リード
  6496:     @Override protected byte mmdRbs (int a) throws M68kException {
  6497:        a &= XEiJ.BUS_MOTHER_MASK;
  6498:        XEiJ.mpuCycleCount += XEiJ.mpuRomWait;
  6499:        return MainMemory.mmrM8[a];
  6500:      }
  6501:     @Override protected int mmdRbz (int a) throws M68kException {
  6502:        a &= XEiJ.BUS_MOTHER_MASK;
  6503:        XEiJ.mpuCycleCount += XEiJ.mpuRomWait;
  6504:        return MainMemory.mmrM8[a] & 255;
  6505:      }
  6506:     @Override protected int mmdRws (int a) throws M68kException {
  6507:        a &= XEiJ.BUS_MOTHER_MASK;
  6508:        XEiJ.mpuCycleCount += XEiJ.mpuRomWait;
  6509:        if (MainMemory.MMR_USE_BYTE_BUFFER) {
  6510:          return MainMemory.mmrBuffer.getShort (a);
  6511:        } else {
  6512:          return MainMemory.mmrM8[a] << 8 | MainMemory.mmrM8[a + 1] & 255;
  6513:        }
  6514:      }
  6515:     @Override protected int mmdRwz (int a) throws M68kException {
  6516:        a &= XEiJ.BUS_MOTHER_MASK;
  6517:        XEiJ.mpuCycleCount += XEiJ.mpuRomWait;
  6518:        if (MainMemory.MMR_USE_BYTE_BUFFER) {
  6519:          return MainMemory.mmrBuffer.getChar (a);
  6520:        } else {
  6521:          return (char) (MainMemory.mmrM8[a] << 8 | MainMemory.mmrM8[a + 1] & 255);
  6522:        }
  6523:      }
  6524:     @Override protected int mmdRls (int a) throws M68kException {
  6525:        a &= XEiJ.BUS_MOTHER_MASK;
  6526:        XEiJ.mpuCycleCount += XEiJ.mpuRomWait << 1;
  6527:        if (MainMemory.MMR_USE_BYTE_BUFFER) {
  6528:          return MainMemory.mmrBuffer.getInt (a);
  6529:        } else {
  6530:          return MainMemory.mmrM8[a] << 24 | (MainMemory.mmrM8[a + 1] & 255) << 16 | (char) (MainMemory.mmrM8[a + 2] << 8 | MainMemory.mmrM8[a + 3] & 255);
  6531:        }
  6532:      }
  6533:   },  //MMD_ROM
  6534: 
  6535:   //--------------------------------------------------------------------------------
  6536:   //MMD_IBP 命令ブレークポイント
  6537:   MMD_IBP {
  6538:     @Override public String toString () {
  6539:       return Multilingual.mlnJapanese ? "命令ブレークポイント" : "Instruction Break Point";
  6540:     }
  6541:     @Override protected int mmdRwz (int a) throws M68kException {
  6542:        if (InstructionBreakPoint.IBP_ON) {
  6543:          InstructionBreakPoint.InstructionBreakRecord[] hashTable = (XEiJ.regSRS != 0 ?
  6544:                                                                      InstructionBreakPoint.ibpSuperHashTable :
  6545:                                                                      InstructionBreakPoint.ibpUserHashTable);
  6546:          for (InstructionBreakPoint.InstructionBreakRecord r = hashTable[a >> 1 & InstructionBreakPoint.IBP_HASH_MASK];
  6547:               r != null;
  6548:               r = r.ibrNext) {  //同じ物理ハッシュコードを持つ命令ブレークポイントについて
  6549:            if (r.ibrPhysicalAddress == a) {  //命令ブレークポイントが設定されているとき
  6550:              if (r.ibrValue == r.ibrTarget) {  //現在値が目標値と一致しているとき
  6551:                if (r.ibrThreshold < 0) {  //インスタントのとき
  6552:                  InstructionBreakPoint.ibpRemove (r.ibrLogicalAddress, XEiJ.regSRS);  //取り除く
  6553:                  XEiJ.mpuContinue = true;  //ステップ実行を継続する
  6554:                } else if (r.ibrTarget < r.ibrThreshold) {  //インスタント化しているとき
  6555:                  r.ibrTarget = r.ibrThreshold;  //目標値を閾値に戻す
  6556:                  XEiJ.mpuContinue = true;  //ステップ実行を継続する
  6557:                } else {  //インスタントでなくインスタント化していないとき
  6558:                  if (r.ibrScriptElement != null &&  //スクリプトが指定されていて
  6559:                      r.ibrScriptElement.exlEval (ExpressionEvaluator.EVM_EXPRESSION).exlFloatValue.iszero ()) {  //条件が成立していないとき
  6560:                    break;  //続行する
  6561:                  }
  6562:                  r.ibrTarget++;  //目標値を増やす
  6563:                  XEiJ.mpuContinue = false;  //ステップ実行を継続しない
  6564:                }
  6565:                M68kException.m6eNumber = -1;  //命令ブレークポイントによる停止。XEiJ.mpuContinueを設定すること
  6566:                throw M68kException.m6eSignal;  //停止する
  6567:              } else {  //現在値が目標値と一致していないとき
  6568:                r.ibrValue++;  //現在値を増やす
  6569:                break;  //続行する
  6570:              }
  6571:            }
  6572:          }
  6573:        }
  6574:        if (DataBreakPoint.DBP_ON) {
  6575:          return DataBreakPoint.dbpMemoryMap[a >>> XEiJ.BUS_PAGE_BITS].mmdRwz (a);
  6576:        } else {
  6577:          return XEiJ.busMemoryMap[a >>> XEiJ.BUS_PAGE_BITS].mmdRwz (a);
  6578:        }
  6579:      }
  6580:   },  //MMD_IBP
  6581: 
  6582:   //--------------------------------------------------------------------------------
  6583:   //MMD_DBP データブレークポイント
  6584:   MMD_DBP {
  6585:     @Override public String toString () {
  6586:       return Multilingual.mlnJapanese ? "データブレークポイント" : "Data Break Point";
  6587:     }
  6588:     //ピーク
  6589:     @Override protected byte mmdPbs (int a) {
  6590:       return (XEiJ.regSRS != 0 ? XEiJ.busSuperMap : XEiJ.busUserMap)[a >>> XEiJ.BUS_PAGE_BITS].mmdPbs (a);
  6591:     }
  6592:     @Override protected int mmdPbz (int a) {
  6593:       return (XEiJ.regSRS != 0 ? XEiJ.busSuperMap : XEiJ.busUserMap)[a >>> XEiJ.BUS_PAGE_BITS].mmdPbz (a);
  6594:     }
  6595:     @Override protected int mmdPws (int a) {
  6596:       return (XEiJ.regSRS != 0 ? XEiJ.busSuperMap : XEiJ.busUserMap)[a >>> XEiJ.BUS_PAGE_BITS].mmdPws (a);
  6597:     }
  6598:     @Override protected int mmdPwz (int a) {
  6599:       return (XEiJ.regSRS != 0 ? XEiJ.busSuperMap : XEiJ.busUserMap)[a >>> XEiJ.BUS_PAGE_BITS].mmdPwz (a);
  6600:     }
  6601:     @Override protected int mmdPls (int a) {
  6602:       return (XEiJ.regSRS != 0 ? XEiJ.busSuperMap : XEiJ.busUserMap)[a >>> XEiJ.BUS_PAGE_BITS].mmdPls (a);
  6603:     }
  6604:     //リード
  6605:     @Override protected byte mmdRbs (int a) throws M68kException {
  6606:        int d = (XEiJ.regSRS != 0 ? XEiJ.busSuperMap : XEiJ.busUserMap)[a >>> XEiJ.BUS_PAGE_BITS].mmdRbs (a);
  6607:        DataBreakPoint.dbpBreak (DataBreakPoint.DBP_BYTE, a, d);
  6608:        return (byte) d;
  6609:      }
  6610:     @Override protected int mmdRbz (int a) throws M68kException {
  6611:        int d = (XEiJ.regSRS != 0 ? XEiJ.busSuperMap : XEiJ.busUserMap)[a >>> XEiJ.BUS_PAGE_BITS].mmdRbz (a);
  6612:        DataBreakPoint.dbpBreak (DataBreakPoint.DBP_BYTE, a, d);
  6613:        return d;
  6614:      }
  6615:     @Override protected int mmdRws (int a) throws M68kException {
  6616:        int d = (XEiJ.regSRS != 0 ? XEiJ.busSuperMap : XEiJ.busUserMap)[a >>> XEiJ.BUS_PAGE_BITS].mmdRws (a);
  6617:        DataBreakPoint.dbpBreak (DataBreakPoint.DBP_WORD, a, d);
  6618:        return d;
  6619:      }
  6620:     @Override protected int mmdRwz (int a) throws M68kException {
  6621:        int d = (XEiJ.regSRS != 0 ? XEiJ.busSuperMap : XEiJ.busUserMap)[a >>> XEiJ.BUS_PAGE_BITS].mmdRwz (a);
  6622:        DataBreakPoint.dbpBreak (DataBreakPoint.DBP_WORD, a, d);
  6623:        return d;
  6624:      }
  6625:     @Override protected int mmdRls (int a) throws M68kException {
  6626:        int d = (XEiJ.regSRS != 0 ? XEiJ.busSuperMap : XEiJ.busUserMap)[a >>> XEiJ.BUS_PAGE_BITS].mmdRls (a);
  6627:        DataBreakPoint.dbpBreak (DataBreakPoint.DBP_LONG, a, d);
  6628:        return d;
  6629:      }
  6630:     //ライト
  6631:     @Override protected void mmdWb (int a, int d) throws M68kException {
  6632:        (XEiJ.regSRS != 0 ? XEiJ.busSuperMap : XEiJ.busUserMap)[a >>> XEiJ.BUS_PAGE_BITS].mmdWb (a, d);
  6633:        DataBreakPoint.dbpBreak (DataBreakPoint.DBP_BYTE, a, d);
  6634:      }
  6635:     @Override protected void mmdWw (int a, int d) throws M68kException {
  6636:        (XEiJ.regSRS != 0 ? XEiJ.busSuperMap : XEiJ.busUserMap)[a >>> XEiJ.BUS_PAGE_BITS].mmdWw (a, d);
  6637:        DataBreakPoint.dbpBreak (DataBreakPoint.DBP_WORD, a, d);
  6638:      }
  6639:     @Override protected void mmdWl (int a, int d) throws M68kException {
  6640:        (XEiJ.regSRS != 0 ? XEiJ.busSuperMap : XEiJ.busUserMap)[a >>> XEiJ.BUS_PAGE_BITS].mmdWl (a, d);
  6641:        DataBreakPoint.dbpBreak (DataBreakPoint.DBP_LONG, a, d);
  6642:      }
  6643:   },  //MMD_DBP
  6644: 
  6645:   //--------------------------------------------------------------------------------
  6646:   //MMD_NUL ヌルデバイス
  6647:   MMD_NUL {
  6648:     @Override public String toString () {
  6649:       return Multilingual.mlnJapanese ? "ヌルデバイス" : "Null Device";
  6650:     }
  6651:   };  //MMD_NUL
  6652: 
  6653:   //--------------------------------------------------------------------------------
  6654:   //ピークのデフォルト
  6655:   //  エラーや副作用なしでリードする
  6656:   //  バスエラーのときは-1をキャストした値を返す
  6657:   //  リードがデバイスの状態を変化させる可能性がある場合は個別に処理すること
  6658:   protected byte mmdPbs (int a) {
  6659:     try {
  6660:       return (byte) mmdRbz (a);
  6661:     } catch (M68kException e) {
  6662:     }
  6663:     return -1;
  6664:   }
  6665:   protected int mmdPbz (int a) {
  6666:     try {
  6667:       return mmdRbz (a);
  6668:     } catch (M68kException e) {
  6669:     }
  6670:     return 255;
  6671:   }
  6672:   protected int mmdPws (int a) {
  6673:     try {
  6674:       return (short) mmdRwz (a);
  6675:     } catch (M68kException e) {
  6676:     }
  6677:     return -1;
  6678:   }
  6679:   protected int mmdPwz (int a) {
  6680:     try {
  6681:       return mmdRwz (a);
  6682:     } catch (M68kException e) {
  6683:     }
  6684:     return 65535;
  6685:   }
  6686:   protected int mmdPls (int a) {
  6687:     try {
  6688:       return mmdRls (a);
  6689:     } catch (M68kException e) {
  6690:     }
  6691:     return -1;
  6692:   }
  6693:   //リードのデフォルト
  6694:   //  バイトとワードの符号拡張はゼロ拡張を呼び出す
  6695:   //  符号なしとロングはバスエラー
  6696:   protected byte mmdRbs (int a) throws M68kException {
  6697:     return (byte) mmdRbz (a);
  6698:   }
  6699:   protected int mmdRbz (int a) throws M68kException {
  6700:     M68kException.m6eFSLW |= M68kException.M6E_FSLW_BUS_ERROR_ON_READ;  //サイズは設定済み。分割されている場合があることに注意
  6701:     M68kException.m6eNumber = M68kException.M6E_ACCESS_FAULT;
  6702:     M68kException.m6eAddress = a;
  6703:     M68kException.m6eDirection = XEiJ.MPU_WR_READ;
  6704:     M68kException.m6eSize = XEiJ.MPU_SS_BYTE;
  6705:     throw M68kException.m6eSignal;
  6706:   }
  6707:   protected int mmdRws (int a) throws M68kException {
  6708:     return (short) mmdRwz (a);
  6709:   }
  6710:   protected int mmdRwz (int a) throws M68kException {
  6711:     M68kException.m6eFSLW |= M68kException.M6E_FSLW_BUS_ERROR_ON_READ;  //サイズは設定済み。分割されている場合があることに注意
  6712:     M68kException.m6eNumber = M68kException.M6E_ACCESS_FAULT;
  6713:     M68kException.m6eAddress = a;
  6714:     M68kException.m6eDirection = XEiJ.MPU_WR_READ;
  6715:     M68kException.m6eSize = XEiJ.MPU_SS_WORD;
  6716:     throw M68kException.m6eSignal;
  6717:   }
  6718:   protected int mmdRls (int a) throws M68kException {
  6719:     M68kException.m6eFSLW |= M68kException.M6E_FSLW_BUS_ERROR_ON_READ;  //サイズは設定済み。分割されている場合があることに注意
  6720:     M68kException.m6eNumber = M68kException.M6E_ACCESS_FAULT;
  6721:     M68kException.m6eAddress = a;
  6722:     M68kException.m6eDirection = XEiJ.MPU_WR_READ;
  6723:     M68kException.m6eSize = XEiJ.MPU_SS_LONG;
  6724:     throw M68kException.m6eSignal;
  6725:   }
  6726:   //ポークのデフォルト
  6727:   //  エラーや副作用なしでライトする
  6728:   //  ライトがデバイスの状態を変化させる可能性がある場合は個別に処理すること
  6729:   protected void mmdVb (int a, int d) {
  6730:     try {
  6731:       mmdWb (a, d);
  6732:     } catch (M68kException e) {
  6733:     }
  6734:   }
  6735:   protected void mmdVw (int a, int d) {
  6736:     try {
  6737:       mmdWw (a, d);
  6738:     } catch (M68kException e) {
  6739:     }
  6740:   }
  6741:   protected void mmdVl (int a, int d) {
  6742:     try {
  6743:       mmdWl (a, d);
  6744:     } catch (M68kException e) {
  6745:     }
  6746:   }
  6747:   //ライトのデフォルト
  6748:   //  すべてバスエラー
  6749:   protected void mmdWb (int a, int d) throws M68kException {
  6750:     M68kException.m6eFSLW |= M68kException.M6E_FSLW_BUS_ERROR_ON_WRITE;  //サイズは設定済み。分割されている場合があることに注意
  6751:     M68kException.m6eNumber = M68kException.M6E_ACCESS_FAULT;
  6752:     M68kException.m6eAddress = a;
  6753:     M68kException.m6eDirection = XEiJ.MPU_WR_WRITE;
  6754:     M68kException.m6eSize = XEiJ.MPU_SS_BYTE;
  6755:     throw M68kException.m6eSignal;
  6756:   }
  6757:   protected void mmdWw (int a, int d) throws M68kException {
  6758:     M68kException.m6eFSLW |= M68kException.M6E_FSLW_BUS_ERROR_ON_WRITE;  //サイズは設定済み。分割されている場合があることに注意
  6759:     M68kException.m6eNumber = M68kException.M6E_ACCESS_FAULT;
  6760:     M68kException.m6eAddress = a;
  6761:     M68kException.m6eDirection = XEiJ.MPU_WR_WRITE;
  6762:     M68kException.m6eSize = XEiJ.MPU_SS_WORD;
  6763:     throw M68kException.m6eSignal;
  6764:   }
  6765:   protected void mmdWl (int a, int d) throws M68kException {
  6766:     M68kException.m6eFSLW |= M68kException.M6E_FSLW_BUS_ERROR_ON_WRITE;  //サイズは設定済み。分割されている場合があることに注意
  6767:     M68kException.m6eNumber = M68kException.M6E_ACCESS_FAULT;
  6768:     M68kException.m6eAddress = a;
  6769:     M68kException.m6eDirection = XEiJ.MPU_WR_WRITE;
  6770:     M68kException.m6eSize = XEiJ.MPU_SS_LONG;
  6771:     throw M68kException.m6eSignal;
  6772:   }
  6773: }  //enum MemoryMappedDevice
  6774: 
  6775: 
  6776: