MemoryMappedDevice.java
     1: //========================================================================================
     2: //  MemoryMappedDevice.java
     3: //    en:Memory mapped device
     4: //    ja:メモリマップトデバイス
     5: //  Copyright (C) 2003-2024 Makoto Kamada
     6: //
     7: //  This file is part of the XEiJ (X68000 Emulator in Java).
     8: //  You can use, modify and redistribute the XEiJ if the conditions are met.
     9: //  Read the XEiJ License for more details.
    10: //  https://stdkmd.net/xeij/
    11: //========================================================================================
    12: 
    13: //----------------------------------------------------------------------------------------
    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] & 0xff;
    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] & 0xff);
    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] & 0xff));
    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] & 0xff) << 16 | (char) (MainMemory.mmrM8[a + 2] << 8 | (MainMemory.mmrM8[a + 3] & 0xff));
    79:       }
    80:     }
    81:     //リード
    82:     @Override protected byte mmdRbs (int a) throws M68kException {
    83:        XEiJ.mpuClockTime += XEiJ.busWaitTime.ram;
    84:        a &= XEiJ.BUS_MOTHER_MASK;
    85:        return MainMemory.mmrM8[a];
    86:      }
    87:     @Override protected int mmdRbz (int a) throws M68kException {
    88:        XEiJ.mpuClockTime += XEiJ.busWaitTime.ram;
    89:        a &= XEiJ.BUS_MOTHER_MASK;
    90:        return MainMemory.mmrM8[a] & 0xff;
    91:      }
    92:     @Override protected int mmdRws (int a) throws M68kException {
    93:        XEiJ.mpuClockTime += XEiJ.busWaitTime.ram;
    94:        a &= XEiJ.BUS_MOTHER_MASK;
    95:        if (MainMemory.MMR_USE_BYTE_BUFFER) {
    96:          return MainMemory.mmrBuffer.getShort (a);
    97:        } else {
    98:          return MainMemory.mmrM8[a] << 8 | (MainMemory.mmrM8[a + 1] & 0xff);
    99:        }
   100:      }
   101:     @Override protected int mmdRwz (int a) throws M68kException {
   102:        XEiJ.mpuClockTime += XEiJ.busWaitTime.ram;
   103:        a &= XEiJ.BUS_MOTHER_MASK;
   104:        if (MainMemory.MMR_USE_BYTE_BUFFER) {
   105:          return MainMemory.mmrBuffer.getChar (a);
   106:        } else {
   107:          return (char) (MainMemory.mmrM8[a] << 8 | (MainMemory.mmrM8[a + 1] & 0xff));
   108:        }
   109:      }
   110:     @Override protected int mmdRls (int a) throws M68kException {
   111:        XEiJ.mpuClockTime += XEiJ.busWaitTime.ramlong;
   112:        a &= XEiJ.BUS_MOTHER_MASK;
   113:        if (MainMemory.MMR_USE_BYTE_BUFFER) {
   114:          return MainMemory.mmrBuffer.getInt (a);
   115:        } else {
   116:          return MainMemory.mmrM8[a] << 24 | (MainMemory.mmrM8[a + 1] & 0xff) << 16 | (char) (MainMemory.mmrM8[a + 2] << 8 | (MainMemory.mmrM8[a + 3] & 0xff));
   117:        }
   118:      }
   119:     //ライト
   120:     @Override protected void mmdWb (int a, int d) throws M68kException {
   121:        XEiJ.mpuClockTime += XEiJ.busWaitTime.ram;
   122:        a &= XEiJ.BUS_MOTHER_MASK;
   123:        MainMemory.mmrM8[a    ] = (byte)  d;
   124:      }
   125:     @Override protected void mmdWw (int a, int d) throws M68kException {
   126:        XEiJ.mpuClockTime += XEiJ.busWaitTime.ram;
   127:        a &= XEiJ.BUS_MOTHER_MASK;
   128:        if (MainMemory.MMR_USE_BYTE_BUFFER) {
   129:          MainMemory.mmrBuffer.putShort (a, (short) d);
   130:        } else {
   131:          MainMemory.mmrM8[a    ] = (byte) (d >> 8);
   132:          MainMemory.mmrM8[a + 1] = (byte)  d;
   133:        }
   134:      }
   135:     @Override protected void mmdWl (int a, int d) throws M68kException {
   136:        XEiJ.mpuClockTime += XEiJ.busWaitTime.ramlong;
   137:        a &= XEiJ.BUS_MOTHER_MASK;
   138:        if (MainMemory.MMR_USE_BYTE_BUFFER) {
   139:          MainMemory.mmrBuffer.putInt (a, d);
   140:        } else {
   141:          MainMemory.mmrM8[a    ] = (byte) (d >> 24);
   142:          MainMemory.mmrM8[a + 1] = (byte) (d >> 16);
   143:          MainMemory.mmrM8[a + 2] = (byte) (d >> 8);
   144:          MainMemory.mmrM8[a + 3] = (byte)  d;
   145:        }
   146:      }
   147:   },  //MMD_MMR
   148: 
   149:   //--------------------------------------------------------------------------------
   150:   //MMD_MM1 1MB搭載機の2MB目
   151:   //  $00100000~$001FFFFF
   152:   //  リードはShodaiは$6100、ACE/PRO/PROIIは$FFFFの繰り返し
   153:   //  ライトは無視
   154:   MMD_MM1 {
   155:     @Override public String toString () {
   156:       return Multilingual.mlnJapanese ? "1MB 搭載機の 2MB 目" : "2nd MB of machines with 1MB";
   157:     }
   158:     //リード
   159:     @Override protected byte mmdRbs (int a) throws M68kException {
   160:        XEiJ.mpuClockTime += XEiJ.busWaitTime.ram;
   161:       return (byte) ((a & 1) == 0 ? mmdRwz (a) >> 8 : mmdRwz (a));
   162:     }
   163:     @Override protected int mmdRbz (int a) throws M68kException {
   164:        XEiJ.mpuClockTime += XEiJ.busWaitTime.ram;
   165:       return (a & 1) == 0 ? mmdRwz (a) >> 8 : mmdRwz (a) & 0xff;
   166:     }
   167:     @Override protected int mmdRws (int a) throws M68kException {
   168:        XEiJ.mpuClockTime += XEiJ.busWaitTime.ram;
   169:       return (short) mmdRwz (a);
   170:     }
   171:     @Override protected int mmdRwz (int a) throws M68kException {
   172:        XEiJ.mpuClockTime += XEiJ.busWaitTime.ram;
   173:       return XEiJ.currentModel.isShodai () ? 0x6100 : 0xffff;
   174:     }
   175:     @Override protected int mmdRls (int a) throws M68kException {
   176:        XEiJ.mpuClockTime += XEiJ.busWaitTime.ramlong;
   177:       return mmdRwz (a) << 16 | mmdRwz (a + 2);
   178:     }
   179:     //ライト
   180:     @Override protected void mmdWb (int a, int d) throws M68kException {
   181:        XEiJ.mpuClockTime += XEiJ.busWaitTime.ram;
   182:      }
   183:     @Override protected void mmdWw (int a, int d) throws M68kException {
   184:        XEiJ.mpuClockTime += XEiJ.busWaitTime.ram;
   185:      }
   186:     @Override protected void mmdWl (int a, int d) throws M68kException {
   187:        XEiJ.mpuClockTime += XEiJ.busWaitTime.ramlong;
   188:      }
   189:   },
   190: 
   191:   //--------------------------------------------------------------------------------
   192:   //MMD_XMM 拡張メモリ
   193:   MMD_XMM {
   194:     @Override public String toString () {
   195:       return Multilingual.mlnJapanese ? "拡張メモリ" : "Expansion Memory";
   196:     }
   197:     //ピーク
   198:     @Override protected byte mmdPbs (int a) {
   199:       a -= XEiJ.busExMemoryStart;
   200:       return XEiJ.busExMemoryArray[a];
   201:     }
   202:     @Override protected int mmdPbz (int a) {
   203:       a -= XEiJ.busExMemoryStart;
   204:       return XEiJ.busExMemoryArray[a] & 0xff;
   205:     }
   206:     @Override protected int mmdPws (int a) {
   207:       a -= XEiJ.busExMemoryStart;
   208:       return XEiJ.busExMemoryArray[a] << 8 | (XEiJ.busExMemoryArray[a + 1] & 0xff);
   209:     }
   210:     @Override protected int mmdPwz (int a) {
   211:       a -= XEiJ.busExMemoryStart;
   212:       return (char) (XEiJ.busExMemoryArray[a] << 8 | (XEiJ.busExMemoryArray[a + 1] & 0xff));
   213:     }
   214:     @Override protected int mmdPls (int a) {
   215:       a -= XEiJ.busExMemoryStart;
   216:       return XEiJ.busExMemoryArray[a] << 24 | (XEiJ.busExMemoryArray[a + 1] & 0xff) << 16 | (char) (XEiJ.busExMemoryArray[a + 2] << 8 | (XEiJ.busExMemoryArray[a + 3] & 0xff));
   217:     }
   218:     //リード
   219:     @Override protected byte mmdRbs (int a) throws M68kException {
   220:        a -= XEiJ.busExMemoryStart;
   221:        return XEiJ.busExMemoryArray[a];
   222:      }
   223:     @Override protected int mmdRbz (int a) throws M68kException {
   224:        a -= XEiJ.busExMemoryStart;
   225:        return XEiJ.busExMemoryArray[a] & 0xff;
   226:      }
   227:     @Override protected int mmdRws (int a) throws M68kException {
   228:        a -= XEiJ.busExMemoryStart;
   229:        return XEiJ.busExMemoryArray[a] << 8 | (XEiJ.busExMemoryArray[a + 1] & 0xff);
   230:      }
   231:     @Override protected int mmdRwz (int a) throws M68kException {
   232:        a -= XEiJ.busExMemoryStart;
   233:        return (char) (XEiJ.busExMemoryArray[a] << 8 | (XEiJ.busExMemoryArray[a + 1] & 0xff));
   234:      }
   235:     @Override protected int mmdRls (int a) throws M68kException {
   236:        a -= XEiJ.busExMemoryStart;
   237:        return XEiJ.busExMemoryArray[a] << 24 | (XEiJ.busExMemoryArray[a + 1] & 0xff) << 16 | (char) (XEiJ.busExMemoryArray[a + 2] << 8 | (XEiJ.busExMemoryArray[a + 3] & 0xff));
   238:      }
   239:     //ライト
   240:     @Override protected void mmdWb (int a, int d) throws M68kException {
   241:        a -= XEiJ.busExMemoryStart;
   242:        XEiJ.busExMemoryArray[a    ] = (byte)  d;
   243:      }
   244:     @Override protected void mmdWw (int a, int d) throws M68kException {
   245:        a -= XEiJ.busExMemoryStart;
   246:        XEiJ.busExMemoryArray[a    ] = (byte) (d >> 8);
   247:        XEiJ.busExMemoryArray[a + 1] = (byte)  d;
   248:      }
   249:     @Override protected void mmdWl (int a, int d) throws M68kException {
   250:        a -= XEiJ.busExMemoryStart;
   251:        XEiJ.busExMemoryArray[a    ] = (byte) (d >> 24);
   252:        XEiJ.busExMemoryArray[a + 1] = (byte) (d >> 16);
   253:        XEiJ.busExMemoryArray[a + 2] = (byte) (d >> 8);
   254:        XEiJ.busExMemoryArray[a + 3] = (byte)  d;
   255:      }
   256:   },  //MMD_XMM
   257: 
   258:   //--------------------------------------------------------------------------------
   259:   //MMD_GE0 グラフィックス画面(512ドット16色ページ0)
   260:   //
   261:   //  512ドット16色
   262:   //                アドレス             アクセス                  格納
   263:   //    GE0  0x00c00000~0x00c7ffff  ............3210  ──  ............3210
   264:   //    GE1  0x00c80000~0x00cfffff  ............7654  ──  ............7654
   265:   //    GE2  0x00d00000~0x00d7ffff  ............ba98  ──  ............ba98
   266:   //    GE3  0x00d80000~0x00dfffff  ............fedc  ──  ............fedc
   267:   //
   268:   MMD_GE0 {
   269:     @Override public String toString () {
   270:       return Multilingual.mlnJapanese ? "グラフィックス画面 (512 ドット 16 色 ページ 0)" : "Graphics Screen (512 dots 16 colors page 0)";
   271:     }
   272:     //ピーク
   273:     @Override protected byte mmdPbs (int a) {
   274:       a &= XEiJ.BUS_MOTHER_MASK;
   275:       return MainMemory.mmrM8[a];
   276:     }
   277:     @Override protected int mmdPbz (int a) {
   278:       a &= XEiJ.BUS_MOTHER_MASK;
   279:       return MainMemory.mmrM8[a];
   280:     }
   281:     @Override protected int mmdPws (int a) {
   282:       a &= XEiJ.BUS_MOTHER_MASK;
   283:       return MainMemory.mmrM8[a + 1];
   284:     }
   285:     @Override protected int mmdPwz (int a) {
   286:       a &= XEiJ.BUS_MOTHER_MASK;
   287:       return MainMemory.mmrM8[a + 1];
   288:     }
   289:     @Override protected int mmdPls (int a) {
   290:       a &= XEiJ.BUS_MOTHER_MASK;
   291:       return MainMemory.mmrM8[a + 1] << 16 | MainMemory.mmrM8[a + 3];
   292:     }
   293:     //リード
   294:     @Override protected byte mmdRbs (int a) throws M68kException {
   295:        XEiJ.mpuClockTime += XEiJ.busWaitTime.gvram;
   296:        a &= XEiJ.BUS_MOTHER_MASK;
   297:        return MainMemory.mmrM8[a];
   298:      }
   299:     @Override protected int mmdRbz (int a) throws M68kException {
   300:        XEiJ.mpuClockTime += XEiJ.busWaitTime.gvram;
   301:        a &= XEiJ.BUS_MOTHER_MASK;
   302:        return MainMemory.mmrM8[a];
   303:      }
   304:     @Override protected int mmdRws (int a) throws M68kException {
   305:        XEiJ.mpuClockTime += XEiJ.busWaitTime.gvram;
   306:        a &= XEiJ.BUS_MOTHER_MASK;
   307:        return MainMemory.mmrM8[a + 1];
   308:      }
   309:     @Override protected int mmdRwz (int a) throws M68kException {
   310:        XEiJ.mpuClockTime += XEiJ.busWaitTime.gvram;
   311:        a &= XEiJ.BUS_MOTHER_MASK;
   312:        return MainMemory.mmrM8[a + 1];
   313:      }
   314:     @Override protected int mmdRls (int a) throws M68kException {
   315:        XEiJ.mpuClockTime += XEiJ.busWaitTime.gvram * 2;
   316:        a &= XEiJ.BUS_MOTHER_MASK;
   317:        return MainMemory.mmrM8[a + 1] << 16 | MainMemory.mmrM8[a + 3];
   318:      }
   319:     //ライト
   320:     @Override protected void mmdWb (int a, int d) throws M68kException {
   321:        XEiJ.mpuClockTime += XEiJ.busWaitTime.gvram;
   322:        a &= XEiJ.BUS_MOTHER_MASK;
   323:        if (XEiJ.TEST_BIT_0_SHIFT ? a << 31 - 0 < 0 : (a & 1) != 0) {
   324:          MainMemory.mmrM8[a] = (byte) (d          & 15);
   325:          int y = (a >> 10) - CRTC.crtR13GrYCurr[0] & 511;
   326:          CRTC.crtRasterStamp[y      ] = 0;
   327:          CRTC.crtRasterStamp[y + 512] = 0;
   328:        }
   329:      }
   330:     @Override protected void mmdWw (int a, int d) throws M68kException {
   331:        XEiJ.mpuClockTime += XEiJ.busWaitTime.gvram;
   332:        a &= XEiJ.BUS_MOTHER_MASK;
   333:        MainMemory.mmrM8[a + 1] = (byte) (d          & 15);
   334:        int y = (a >> 10) - CRTC.crtR13GrYCurr[0] & 511;
   335:        CRTC.crtRasterStamp[y      ] = 0;
   336:        CRTC.crtRasterStamp[y + 512] = 0;
   337:      }
   338:     @Override protected void mmdWl (int a, int d) throws M68kException {
   339:        XEiJ.mpuClockTime += XEiJ.busWaitTime.gvram * 2;
   340:        a &= XEiJ.BUS_MOTHER_MASK;
   341:        MainMemory.mmrM8[a + 1] = (byte) (d << 12  >>> 28);
   342:        MainMemory.mmrM8[a + 3] = (byte) (d          & 15);
   343:        int y = (a >> 10) - CRTC.crtR13GrYCurr[0] & 511;
   344:        CRTC.crtRasterStamp[y      ] = 0;
   345:        CRTC.crtRasterStamp[y + 512] = 0;
   346:      }
   347:   },  //MMD_GE0
   348: 
   349:   //--------------------------------------------------------------------------------
   350:   //MMD_GE1 グラフィックス画面(512ドット16色ページ1)
   351:   //
   352:   //  512ドット16色
   353:   //                アドレス             アクセス                  格納
   354:   //    GE0  0x00c00000~0x00c7ffff  ............3210  ──  ............3210
   355:   //    GE1  0x00c80000~0x00cfffff  ............7654  ──  ............7654
   356:   //    GE2  0x00d00000~0x00d7ffff  ............ba98  ──  ............ba98
   357:   //    GE3  0x00d80000~0x00dfffff  ............fedc  ──  ............fedc
   358:   //
   359:   MMD_GE1 {
   360:     @Override public String toString () {
   361:       return Multilingual.mlnJapanese ? "グラフィックス画面 (512 ドット 16 色 ページ 1)" : "Graphics Screen (512 dots 16 colors page 1)";
   362:     }
   363:     //ピーク
   364:     @Override protected byte mmdPbs (int a) {
   365:       a &= XEiJ.BUS_MOTHER_MASK;
   366:       return MainMemory.mmrM8[a];
   367:     }
   368:     @Override protected int mmdPbz (int a) {
   369:       a &= XEiJ.BUS_MOTHER_MASK;
   370:       return MainMemory.mmrM8[a];
   371:     }
   372:     @Override protected int mmdPws (int a) {
   373:       a &= XEiJ.BUS_MOTHER_MASK;
   374:       return MainMemory.mmrM8[a + 1];
   375:     }
   376:     @Override protected int mmdPwz (int a) {
   377:       a &= XEiJ.BUS_MOTHER_MASK;
   378:       return MainMemory.mmrM8[a + 1];
   379:     }
   380:     @Override protected int mmdPls (int a) {
   381:       a &= XEiJ.BUS_MOTHER_MASK;
   382:       return MainMemory.mmrM8[a + 1] << 16 | MainMemory.mmrM8[a + 3];
   383:     }
   384:     //リード
   385:     @Override protected byte mmdRbs (int a) throws M68kException {
   386:        XEiJ.mpuClockTime += XEiJ.busWaitTime.gvram;
   387:        a &= XEiJ.BUS_MOTHER_MASK;
   388:        return MainMemory.mmrM8[a];
   389:      }
   390:     @Override protected int mmdRbz (int a) throws M68kException {
   391:        XEiJ.mpuClockTime += XEiJ.busWaitTime.gvram;
   392:        a &= XEiJ.BUS_MOTHER_MASK;
   393:        return MainMemory.mmrM8[a];
   394:      }
   395:     @Override protected int mmdRws (int a) throws M68kException {
   396:        XEiJ.mpuClockTime += XEiJ.busWaitTime.gvram;
   397:        a &= XEiJ.BUS_MOTHER_MASK;
   398:        return MainMemory.mmrM8[a + 1];
   399:      }
   400:     @Override protected int mmdRwz (int a) throws M68kException {
   401:        XEiJ.mpuClockTime += XEiJ.busWaitTime.gvram;
   402:        a &= XEiJ.BUS_MOTHER_MASK;
   403:        return MainMemory.mmrM8[a + 1];
   404:      }
   405:     @Override protected int mmdRls (int a) throws M68kException {
   406:        XEiJ.mpuClockTime += XEiJ.busWaitTime.gvram * 2;
   407:        a &= XEiJ.BUS_MOTHER_MASK;
   408:        return MainMemory.mmrM8[a + 1] << 16 | MainMemory.mmrM8[a + 3];
   409:      }
   410:     //ライト
   411:     @Override protected void mmdWb (int a, int d) throws M68kException {
   412:        XEiJ.mpuClockTime += XEiJ.busWaitTime.gvram;
   413:        a &= XEiJ.BUS_MOTHER_MASK;
   414:        if (XEiJ.TEST_BIT_0_SHIFT ? a << 31 - 0 < 0 : (a & 1) != 0) {
   415:          MainMemory.mmrM8[a] = (byte) (d          & 15);
   416:          int y = (a >> 10) - CRTC.crtR13GrYCurr[1] & 511;
   417:          CRTC.crtRasterStamp[y      ] = 0;
   418:          CRTC.crtRasterStamp[y + 512] = 0;
   419:        }
   420:      }
   421:     @Override protected void mmdWw (int a, int d) throws M68kException {
   422:        XEiJ.mpuClockTime += XEiJ.busWaitTime.gvram;
   423:        a &= XEiJ.BUS_MOTHER_MASK;
   424:        MainMemory.mmrM8[a + 1] = (byte) (d          & 15);
   425:        int y = (a >> 10) - CRTC.crtR13GrYCurr[1] & 511;
   426:        CRTC.crtRasterStamp[y      ] = 0;
   427:        CRTC.crtRasterStamp[y + 512] = 0;
   428:      }
   429:     @Override protected void mmdWl (int a, int d) throws M68kException {
   430:        XEiJ.mpuClockTime += XEiJ.busWaitTime.gvram * 2;
   431:        a &= XEiJ.BUS_MOTHER_MASK;
   432:        MainMemory.mmrM8[a + 1] = (byte) (d << 12  >>> 28);
   433:        MainMemory.mmrM8[a + 3] = (byte) (d          & 15);
   434:        int y = (a >> 10) - CRTC.crtR13GrYCurr[1] & 511;
   435:        CRTC.crtRasterStamp[y      ] = 0;
   436:        CRTC.crtRasterStamp[y + 512] = 0;
   437:      }
   438:   },  //MMD_GE1
   439: 
   440:   //--------------------------------------------------------------------------------
   441:   //MMD_GE2 グラフィックス画面(512ドット16色ページ2)
   442:   //
   443:   //  512ドット16色
   444:   //                アドレス             アクセス                  格納
   445:   //    GE0  0x00c00000~0x00c7ffff  ............3210  ──  ............3210
   446:   //    GE1  0x00c80000~0x00cfffff  ............7654  ──  ............7654
   447:   //    GE2  0x00d00000~0x00d7ffff  ............ba98  ──  ............ba98
   448:   //    GE3  0x00d80000~0x00dfffff  ............fedc  ──  ............fedc
   449:   //
   450:   MMD_GE2 {
   451:     @Override public String toString () {
   452:       return Multilingual.mlnJapanese ? "グラフィックス画面 (512 ドット 16 色 ページ 2)" : "Graphics Screen (512 dots 16 colors page 2)";
   453:     }
   454:     //ピーク
   455:     @Override protected byte mmdPbs (int a) {
   456:       a &= XEiJ.BUS_MOTHER_MASK;
   457:       return MainMemory.mmrM8[a];
   458:     }
   459:     @Override protected int mmdPbz (int a) {
   460:       a &= XEiJ.BUS_MOTHER_MASK;
   461:       return MainMemory.mmrM8[a];
   462:     }
   463:     @Override protected int mmdPws (int a) {
   464:       a &= XEiJ.BUS_MOTHER_MASK;
   465:       return MainMemory.mmrM8[a + 1];
   466:     }
   467:     @Override protected int mmdPwz (int a) {
   468:       a &= XEiJ.BUS_MOTHER_MASK;
   469:       return MainMemory.mmrM8[a + 1];
   470:     }
   471:     @Override protected int mmdPls (int a) {
   472:       a &= XEiJ.BUS_MOTHER_MASK;
   473:       return MainMemory.mmrM8[a + 1] << 16 | MainMemory.mmrM8[a + 3];
   474:     }
   475:     //リード
   476:     @Override protected byte mmdRbs (int a) throws M68kException {
   477:        XEiJ.mpuClockTime += XEiJ.busWaitTime.gvram;
   478:        a &= XEiJ.BUS_MOTHER_MASK;
   479:        return MainMemory.mmrM8[a];
   480:      }
   481:     @Override protected int mmdRbz (int a) throws M68kException {
   482:        XEiJ.mpuClockTime += XEiJ.busWaitTime.gvram;
   483:        a &= XEiJ.BUS_MOTHER_MASK;
   484:        return MainMemory.mmrM8[a];
   485:      }
   486:     @Override protected int mmdRws (int a) throws M68kException {
   487:        XEiJ.mpuClockTime += XEiJ.busWaitTime.gvram;
   488:        a &= XEiJ.BUS_MOTHER_MASK;
   489:        return MainMemory.mmrM8[a + 1];
   490:      }
   491:     @Override protected int mmdRwz (int a) throws M68kException {
   492:        XEiJ.mpuClockTime += XEiJ.busWaitTime.gvram;
   493:        a &= XEiJ.BUS_MOTHER_MASK;
   494:        return MainMemory.mmrM8[a + 1];
   495:      }
   496:     @Override protected int mmdRls (int a) throws M68kException {
   497:        XEiJ.mpuClockTime += XEiJ.busWaitTime.gvram * 2;
   498:        a &= XEiJ.BUS_MOTHER_MASK;
   499:        return MainMemory.mmrM8[a + 1] << 16 | MainMemory.mmrM8[a + 3];
   500:      }
   501:     //ライト
   502:     @Override protected void mmdWb (int a, int d) throws M68kException {
   503:        XEiJ.mpuClockTime += XEiJ.busWaitTime.gvram;
   504:        a &= XEiJ.BUS_MOTHER_MASK;
   505:        if (XEiJ.TEST_BIT_0_SHIFT ? a << 31 - 0 < 0 : (a & 1) != 0) {
   506:          MainMemory.mmrM8[a] = (byte) (d          & 15);
   507:          int y = (a >> 10) - CRTC.crtR13GrYCurr[2] & 511;
   508:          CRTC.crtRasterStamp[y      ] = 0;
   509:          CRTC.crtRasterStamp[y + 512] = 0;
   510:        }
   511:      }
   512:     @Override protected void mmdWw (int a, int d) throws M68kException {
   513:        XEiJ.mpuClockTime += XEiJ.busWaitTime.gvram;
   514:        a &= XEiJ.BUS_MOTHER_MASK;
   515:        MainMemory.mmrM8[a + 1] = (byte) (d          & 15);
   516:        int y = (a >> 10) - CRTC.crtR13GrYCurr[2] & 511;
   517:        CRTC.crtRasterStamp[y      ] = 0;
   518:        CRTC.crtRasterStamp[y + 512] = 0;
   519:      }
   520:     @Override protected void mmdWl (int a, int d) throws M68kException {
   521:        XEiJ.mpuClockTime += XEiJ.busWaitTime.gvram * 2;
   522:        a &= XEiJ.BUS_MOTHER_MASK;
   523:        MainMemory.mmrM8[a + 1] = (byte) (d << 12  >>> 28);
   524:        MainMemory.mmrM8[a + 3] = (byte) (d          & 15);
   525:        int y = (a >> 10) - CRTC.crtR13GrYCurr[2] & 511;
   526:        CRTC.crtRasterStamp[y      ] = 0;
   527:        CRTC.crtRasterStamp[y + 512] = 0;
   528:      }
   529:   },  //MMD_GE2
   530: 
   531:   //--------------------------------------------------------------------------------
   532:   //MMD_GE3 グラフィックス画面(512ドット16色ページ3)
   533:   //
   534:   //  512ドット16色
   535:   //                アドレス             アクセス                  格納
   536:   //    GE0  0x00c00000~0x00c7ffff  ............3210  ──  ............3210
   537:   //    GE1  0x00c80000~0x00cfffff  ............7654  ──  ............7654
   538:   //    GE2  0x00d00000~0x00d7ffff  ............ba98  ──  ............ba98
   539:   //    GE3  0x00d80000~0x00dfffff  ............fedc  ──  ............fedc
   540:   //
   541:   MMD_GE3 {
   542:     @Override public String toString () {
   543:       return Multilingual.mlnJapanese ? "グラフィックス画面 (512 ドット 16 色 ページ 3)" : "Graphics Screen (512 dots 16 colors page 3)";
   544:     }
   545:     //ピーク
   546:     @Override protected byte mmdPbs (int a) {
   547:       a &= XEiJ.BUS_MOTHER_MASK;
   548:       return MainMemory.mmrM8[a];
   549:     }
   550:     @Override protected int mmdPbz (int a) {
   551:       a &= XEiJ.BUS_MOTHER_MASK;
   552:       return MainMemory.mmrM8[a];
   553:     }
   554:     @Override protected int mmdPws (int a) {
   555:       a &= XEiJ.BUS_MOTHER_MASK;
   556:       return MainMemory.mmrM8[a + 1];
   557:     }
   558:     @Override protected int mmdPwz (int a) {
   559:       a &= XEiJ.BUS_MOTHER_MASK;
   560:       return MainMemory.mmrM8[a + 1];
   561:     }
   562:     @Override protected int mmdPls (int a) {
   563:       a &= XEiJ.BUS_MOTHER_MASK;
   564:       return MainMemory.mmrM8[a + 1] << 16 | MainMemory.mmrM8[a + 3];
   565:     }
   566:     //リード
   567:     @Override protected byte mmdRbs (int a) throws M68kException {
   568:        XEiJ.mpuClockTime += XEiJ.busWaitTime.gvram;
   569:        a &= XEiJ.BUS_MOTHER_MASK;
   570:        return MainMemory.mmrM8[a];
   571:      }
   572:     @Override protected int mmdRbz (int a) throws M68kException {
   573:        XEiJ.mpuClockTime += XEiJ.busWaitTime.gvram;
   574:        a &= XEiJ.BUS_MOTHER_MASK;
   575:        return MainMemory.mmrM8[a];
   576:      }
   577:     @Override protected int mmdRws (int a) throws M68kException {
   578:        XEiJ.mpuClockTime += XEiJ.busWaitTime.gvram;
   579:        a &= XEiJ.BUS_MOTHER_MASK;
   580:        return MainMemory.mmrM8[a + 1];
   581:      }
   582:     @Override protected int mmdRwz (int a) throws M68kException {
   583:        XEiJ.mpuClockTime += XEiJ.busWaitTime.gvram;
   584:        a &= XEiJ.BUS_MOTHER_MASK;
   585:        return MainMemory.mmrM8[a + 1];
   586:      }
   587:     @Override protected int mmdRls (int a) throws M68kException {
   588:        XEiJ.mpuClockTime += XEiJ.busWaitTime.gvram * 2;
   589:        a &= XEiJ.BUS_MOTHER_MASK;
   590:        return MainMemory.mmrM8[a + 1] << 16 | MainMemory.mmrM8[a + 3];
   591:      }
   592:     //ライト
   593:     @Override protected void mmdWb (int a, int d) throws M68kException {
   594:        XEiJ.mpuClockTime += XEiJ.busWaitTime.gvram;
   595:        a &= XEiJ.BUS_MOTHER_MASK;
   596:        if (XEiJ.TEST_BIT_0_SHIFT ? a << 31 - 0 < 0 : (a & 1) != 0) {
   597:          MainMemory.mmrM8[a] = (byte) (d          & 15);
   598:          int y = (a >> 10) - CRTC.crtR13GrYCurr[3] & 511;
   599:          CRTC.crtRasterStamp[y      ] = 0;
   600:          CRTC.crtRasterStamp[y + 512] = 0;
   601:        }
   602:      }
   603:     @Override protected void mmdWw (int a, int d) throws M68kException {
   604:        XEiJ.mpuClockTime += XEiJ.busWaitTime.gvram;
   605:        a &= XEiJ.BUS_MOTHER_MASK;
   606:        MainMemory.mmrM8[a + 1] = (byte) (d          & 15);
   607:        int y = (a >> 10) - CRTC.crtR13GrYCurr[3] & 511;
   608:        CRTC.crtRasterStamp[y      ] = 0;
   609:        CRTC.crtRasterStamp[y + 512] = 0;
   610:      }
   611:     @Override protected void mmdWl (int a, int d) throws M68kException {
   612:        XEiJ.mpuClockTime += XEiJ.busWaitTime.gvram * 2;
   613:        a &= XEiJ.BUS_MOTHER_MASK;
   614:        MainMemory.mmrM8[a + 1] = (byte) (d << 12  >>> 28);
   615:        MainMemory.mmrM8[a + 3] = (byte) (d          & 15);
   616:        int y = (a >> 10) - CRTC.crtR13GrYCurr[3] & 511;
   617:        CRTC.crtRasterStamp[y      ] = 0;
   618:        CRTC.crtRasterStamp[y + 512] = 0;
   619:      }
   620:   },  //MMD_GE3
   621: 
   622:   //--------------------------------------------------------------------------------
   623:   //MMD_GF0 グラフィックス画面(512ドット256色ページ0)
   624:   //
   625:   //  512ドット256色
   626:   //                アドレス             アクセス                  格納
   627:   //    GF0  0x00c00000~0x00c7ffff  ........76543210  ─┬  ............3210
   628:   //    GF1  0x00c80000~0x00cfffff  ........fedcba98  ┐└  ............7654
   629:   //         0x00d00000~0x00d7ffff                    ├─  ............ba98
   630:   //         0x00d80000~0x00dfffff                    └─  ............fedc
   631:   //
   632:   MMD_GF0 {
   633:     @Override public String toString () {
   634:       return Multilingual.mlnJapanese ? "グラフィックス画面 (512 ドット 256 色 ページ 0)" : "Graphics Screen (512 dots 256 colors page 0)";
   635:     }
   636:     //ピーク
   637:     @Override protected byte mmdPbs (int a) {
   638:       a &= XEiJ.BUS_MOTHER_MASK;
   639:       return (byte) (MainMemory.mmrM8[a + 0x00080000] << 4 | MainMemory.mmrM8[a]);
   640:     }
   641:     @Override protected int mmdPbz (int a) {
   642:       a &= XEiJ.BUS_MOTHER_MASK;
   643:       return MainMemory.mmrM8[a + 0x00080000] << 4 | MainMemory.mmrM8[a];
   644:     }
   645:     @Override protected int mmdPws (int a) {
   646:       a &= XEiJ.BUS_MOTHER_MASK;
   647:       return MainMemory.mmrM8[a + 0x00080001] << 4 | MainMemory.mmrM8[a + 1];
   648:     }
   649:     @Override protected int mmdPwz (int a) {
   650:       a &= XEiJ.BUS_MOTHER_MASK;
   651:       return MainMemory.mmrM8[a + 0x00080001] << 4 | MainMemory.mmrM8[a + 1];
   652:     }
   653:     @Override protected int mmdPls (int a) {
   654:       a &= XEiJ.BUS_MOTHER_MASK;
   655:       return MainMemory.mmrM8[a + 0x00080001] << 20 | MainMemory.mmrM8[a + 1] << 16 | MainMemory.mmrM8[a + 0x00080003] << 4 | MainMemory.mmrM8[a + 3];
   656:     }
   657:     //リード
   658:     @Override protected byte mmdRbs (int a) throws M68kException {
   659:        XEiJ.mpuClockTime += XEiJ.busWaitTime.gvram;
   660:        a &= XEiJ.BUS_MOTHER_MASK;
   661:        return (byte) (MainMemory.mmrM8[a + 0x00080000] << 4 | MainMemory.mmrM8[a]);
   662:      }
   663:     @Override protected int mmdRbz (int a) throws M68kException {
   664:        XEiJ.mpuClockTime += XEiJ.busWaitTime.gvram;
   665:        a &= XEiJ.BUS_MOTHER_MASK;
   666:        return MainMemory.mmrM8[a + 0x00080000] << 4 | MainMemory.mmrM8[a];
   667:      }
   668:     @Override protected int mmdRws (int a) throws M68kException {
   669:        XEiJ.mpuClockTime += XEiJ.busWaitTime.gvram;
   670:        a &= XEiJ.BUS_MOTHER_MASK;
   671:        return MainMemory.mmrM8[a + 0x00080001] << 4 | MainMemory.mmrM8[a + 1];
   672:      }
   673:     @Override protected int mmdRwz (int a) throws M68kException {
   674:        XEiJ.mpuClockTime += XEiJ.busWaitTime.gvram;
   675:        a &= XEiJ.BUS_MOTHER_MASK;
   676:        return MainMemory.mmrM8[a + 0x00080001] << 4 | MainMemory.mmrM8[a + 1];
   677:      }
   678:     @Override protected int mmdRls (int a) throws M68kException {
   679:        XEiJ.mpuClockTime += XEiJ.busWaitTime.gvram * 2;
   680:        a &= XEiJ.BUS_MOTHER_MASK;
   681:        return MainMemory.mmrM8[a + 0x00080001] << 20 | MainMemory.mmrM8[a + 1] << 16 | MainMemory.mmrM8[a + 0x00080003] << 4 | MainMemory.mmrM8[a + 3];
   682:      }
   683:     //ライト
   684:     @Override protected void mmdWb (int a, int d) throws M68kException {
   685:        XEiJ.mpuClockTime += XEiJ.busWaitTime.gvram;
   686:        a &= XEiJ.BUS_MOTHER_MASK;
   687:        if (XEiJ.TEST_BIT_0_SHIFT ? a << 31 - 0 < 0 : (a & 1) != 0) {
   688:          MainMemory.mmrM8[a + 0x00080000] = (byte) (d << 24  >>> 28);
   689:          MainMemory.mmrM8[a             ] = (byte) (d          & 15);
   690:          a >>= 10;
   691:          int y = a - CRTC.crtR13GrYCurr[0] & 511;
   692:          CRTC.crtRasterStamp[y      ] = 0;
   693:          CRTC.crtRasterStamp[y + 512] = 0;
   694:          y = a - CRTC.crtR13GrYCurr[1] & 511;
   695:          CRTC.crtRasterStamp[y      ] = 0;
   696:          CRTC.crtRasterStamp[y + 512] = 0;
   697:        }
   698:      }
   699:     @Override protected void mmdWw (int a, int d) throws M68kException {
   700:        XEiJ.mpuClockTime += XEiJ.busWaitTime.gvram;
   701:        a &= XEiJ.BUS_MOTHER_MASK;
   702:        MainMemory.mmrM8[a + 0x00080001] = (byte) (d << 24  >>> 28);
   703:        MainMemory.mmrM8[a + 0x00000001] = (byte) (d          & 15);
   704:        a >>= 10;
   705:        int y = a - CRTC.crtR13GrYCurr[0] & 511;
   706:        CRTC.crtRasterStamp[y      ] = 0;
   707:        CRTC.crtRasterStamp[y + 512] = 0;
   708:        y = a - CRTC.crtR13GrYCurr[1] & 511;
   709:        CRTC.crtRasterStamp[y      ] = 0;
   710:        CRTC.crtRasterStamp[y + 512] = 0;
   711:      }
   712:     @Override protected void mmdWl (int a, int d) throws M68kException {
   713:        XEiJ.mpuClockTime += XEiJ.busWaitTime.gvram * 2;
   714:        a &= XEiJ.BUS_MOTHER_MASK;
   715:        MainMemory.mmrM8[a + 0x00080001] = (byte) (d <<  8  >>> 28);
   716:        MainMemory.mmrM8[a + 0x00000001] = (byte) (d << 12  >>> 28);
   717:        MainMemory.mmrM8[a + 0x00080003] = (byte) (d << 24  >>> 28);
   718:        MainMemory.mmrM8[a + 0x00000003] = (byte) (d          & 15);
   719:        a >>= 10;
   720:        int y = a - CRTC.crtR13GrYCurr[0] & 511;
   721:        CRTC.crtRasterStamp[y      ] = 0;
   722:        CRTC.crtRasterStamp[y + 512] = 0;
   723:        y = a - CRTC.crtR13GrYCurr[1] & 511;
   724:        CRTC.crtRasterStamp[y      ] = 0;
   725:        CRTC.crtRasterStamp[y + 512] = 0;
   726:      }
   727:   },  //MMD_GF0
   728: 
   729:   //--------------------------------------------------------------------------------
   730:   //MMD_GF1 グラフィックス画面(512ドット256色ページ1)
   731:   //
   732:   //  512ドット256色
   733:   //                アドレス             アクセス                  格納
   734:   //    GF0  0x00c00000~0x00c7ffff  ........76543210  ─┬  ............3210
   735:   //    GF1  0x00c80000~0x00cfffff  ........fedcba98  ┐└  ............7654
   736:   //         0x00d00000~0x00d7ffff                    ├─  ............ba98
   737:   //         0x00d80000~0x00dfffff                    └─  ............fedc
   738:   //
   739:   MMD_GF1 {
   740:     @Override public String toString () {
   741:       return Multilingual.mlnJapanese ? "グラフィックス画面 (512 ドット 256 色 ページ 1)" : "Graphics Screen (512 dots 256 colors page 1)";
   742:     }
   743:     //ピーク
   744:     @Override protected byte mmdPbs (int a) {
   745:       a &= XEiJ.BUS_MOTHER_MASK;
   746:       return (byte) (MainMemory.mmrM8[a + 0x00100000] << 4 | MainMemory.mmrM8[a + 0x00080000]);
   747:     }
   748:     @Override protected int mmdPbz (int a) {
   749:       a &= XEiJ.BUS_MOTHER_MASK;
   750:       return MainMemory.mmrM8[a + 0x00100000] << 4 | MainMemory.mmrM8[a + 0x00080000];
   751:     }
   752:     @Override protected int mmdPws (int a) {
   753:       a &= XEiJ.BUS_MOTHER_MASK;
   754:       return MainMemory.mmrM8[a + 0x00100001] << 4 | MainMemory.mmrM8[a + 0x00080001];
   755:     }
   756:     @Override protected int mmdPwz (int a) {
   757:       a &= XEiJ.BUS_MOTHER_MASK;
   758:       return MainMemory.mmrM8[a + 0x00100001] << 4 | MainMemory.mmrM8[a + 0x00080001];
   759:     }
   760:     @Override protected int mmdPls (int a) {
   761:       a &= XEiJ.BUS_MOTHER_MASK;
   762:       return MainMemory.mmrM8[a + 0x00100001] << 20 | MainMemory.mmrM8[a + 0x00080001] << 16 | MainMemory.mmrM8[a + 0x00100003] << 4 | MainMemory.mmrM8[a + 0x00080003];
   763:     }
   764:     //リード
   765:     @Override protected byte mmdRbs (int a) throws M68kException {
   766:        XEiJ.mpuClockTime += XEiJ.busWaitTime.gvram;
   767:        a &= XEiJ.BUS_MOTHER_MASK;
   768:        return (byte) (MainMemory.mmrM8[a + 0x00100000] << 4 | MainMemory.mmrM8[a + 0x00080000]);
   769:      }
   770:     @Override protected int mmdRbz (int a) throws M68kException {
   771:        XEiJ.mpuClockTime += XEiJ.busWaitTime.gvram;
   772:        a &= XEiJ.BUS_MOTHER_MASK;
   773:        return MainMemory.mmrM8[a + 0x00100000] << 4 | MainMemory.mmrM8[a + 0x00080000];
   774:      }
   775:     @Override protected int mmdRws (int a) throws M68kException {
   776:        XEiJ.mpuClockTime += XEiJ.busWaitTime.gvram;
   777:        a &= XEiJ.BUS_MOTHER_MASK;
   778:        return MainMemory.mmrM8[a + 0x00100001] << 4 | MainMemory.mmrM8[a + 0x00080001];
   779:      }
   780:     @Override protected int mmdRwz (int a) throws M68kException {
   781:        XEiJ.mpuClockTime += XEiJ.busWaitTime.gvram;
   782:        a &= XEiJ.BUS_MOTHER_MASK;
   783:        return MainMemory.mmrM8[a + 0x00100001] << 4 | MainMemory.mmrM8[a + 0x00080001];
   784:      }
   785:     @Override protected int mmdRls (int a) throws M68kException {
   786:        XEiJ.mpuClockTime += XEiJ.busWaitTime.gvram * 2;
   787:        a &= XEiJ.BUS_MOTHER_MASK;
   788:        return MainMemory.mmrM8[a + 0x00100001] << 20 | MainMemory.mmrM8[a + 0x00080001] << 16 | MainMemory.mmrM8[a + 0x00100003] << 4 | MainMemory.mmrM8[a + 0x00080003];
   789:      }
   790:     //ライト
   791:     @Override protected void mmdWb (int a, int d) throws M68kException {
   792:        XEiJ.mpuClockTime += XEiJ.busWaitTime.gvram;
   793:        a &= XEiJ.BUS_MOTHER_MASK;
   794:        if (XEiJ.TEST_BIT_0_SHIFT ? a << 31 - 0 < 0 : (a & 1) != 0) {
   795:          MainMemory.mmrM8[a + 0x00100000] = (byte) (d << 24  >>> 28);
   796:          MainMemory.mmrM8[a + 0x00080000] = (byte) (d          & 15);
   797:          a >>= 10;
   798:          int y = a - CRTC.crtR13GrYCurr[2] & 511;
   799:          CRTC.crtRasterStamp[y      ] = 0;
   800:          CRTC.crtRasterStamp[y + 512] = 0;
   801:          y = a - CRTC.crtR13GrYCurr[3] & 511;
   802:          CRTC.crtRasterStamp[y      ] = 0;
   803:          CRTC.crtRasterStamp[y + 512] = 0;
   804:        }
   805:      }
   806:     @Override protected void mmdWw (int a, int d) throws M68kException {
   807:        XEiJ.mpuClockTime += XEiJ.busWaitTime.gvram;
   808:        a &= XEiJ.BUS_MOTHER_MASK;
   809:        MainMemory.mmrM8[a + 0x00100001] = (byte) (d << 24  >>> 28);
   810:        MainMemory.mmrM8[a + 0x00080001] = (byte) (d          & 15);
   811:        a >>= 10;
   812:        int y = a - CRTC.crtR13GrYCurr[2] & 511;
   813:        CRTC.crtRasterStamp[y      ] = 0;
   814:        CRTC.crtRasterStamp[y + 512] = 0;
   815:        y = a - CRTC.crtR13GrYCurr[3] & 511;
   816:        CRTC.crtRasterStamp[y      ] = 0;
   817:        CRTC.crtRasterStamp[y + 512] = 0;
   818:      }
   819:     @Override protected void mmdWl (int a, int d) throws M68kException {
   820:        XEiJ.mpuClockTime += XEiJ.busWaitTime.gvram * 2;
   821:        a &= XEiJ.BUS_MOTHER_MASK;
   822:        MainMemory.mmrM8[a + 0x00100001] = (byte) (d <<  8  >>> 28);
   823:        MainMemory.mmrM8[a + 0x00080001] = (byte) (d << 12  >>> 28);
   824:        MainMemory.mmrM8[a + 0x00100003] = (byte) (d << 24  >>> 28);
   825:        MainMemory.mmrM8[a + 0x00080003] = (byte) (d          & 15);
   826:        a >>= 10;
   827:        int y = a - CRTC.crtR13GrYCurr[2] & 511;
   828:        CRTC.crtRasterStamp[y      ] = 0;
   829:        CRTC.crtRasterStamp[y + 512] = 0;
   830:        y = a - CRTC.crtR13GrYCurr[3] & 511;
   831:        CRTC.crtRasterStamp[y      ] = 0;
   832:        CRTC.crtRasterStamp[y + 512] = 0;
   833:      }
   834:   },  //MMD_GF1
   835: 
   836:   //--------------------------------------------------------------------------------
   837:   //MMD_GM2 グラフィックス画面(メモリモード2)
   838:   //
   839:   //  バイトリード
   840:   //    0x00c00000  0x00が読み出される
   841:   //    0x00c00001  4bitページ1-0が読み出される
   842:   //    0x00c80000  0x00が読み出される
   843:   //    0x00c80001  0x00が読み出される
   844:   //    0x00d00000  0x00が読み出される
   845:   //    0x00d00001  4bitページ1-0が読み出される
   846:   //    0x00d80000  0x00が読み出される
   847:   //    0x00d80001  0x00が読み出される
   848:   //
   849:   //  ワードリード
   850:   //    0x00c00000  上位バイトは0x00で下位バイトに4bitページ1-0が読み出される
   851:   //    0x00c80000  上位バイトは0x00で下位バイトに4bitページ3-2が読み出される
   852:   //    0x00d00000  上位バイトは0x00で下位バイトに4bitページ1-0が読み出される
   853:   //    0x00d80000  上位バイトは0x00で下位バイトに4bitページ3-2が読み出される
   854:   //
   855:   //  バイトライト
   856:   //    0x00c00000  060turboの060モードのときデータは無視され0x00が4bitページ3-2に書き込まれる。それ以外はデータが4bitページ3-2に書き込まれる
   857:   //    0x00c00001  データが4bitページ1-0に書き込まれる
   858:   //    0x00c80000  060turboの060モードのときデータは無視され0x00が4bitページ3-2に書き込まれる。それ以外はデータが4bitページ3-2に書き込まれる
   859:   //    0x00c80001  データが4bitページ1-0に書き込まれる
   860:   //    0x00d00000  060turboの060モードのときデータは無視され0x00が4bitページ3-2に書き込まれる。それ以外はデータが4bitページ3-2に書き込まれる
   861:   //    0x00d00001  データが4bitページ1-0に書き込まれる
   862:   //    0x00d80000  060turboの060モードのときデータは無視され0x00が4bitページ3-2に書き込まれる。それ以外はデータが4bitページ3-2に書き込まれる
   863:   //    0x00d80001  データが4bitページ1-0に書き込まれる
   864:   //
   865:   //  ワードライト
   866:   //    0x00c00000  上位バイトは無視され下位バイトが4bitページ3-2と4bitページ1-0の両方に書き込まれる
   867:   //    0x00c80000  上位バイトは無視され下位バイトが4bitページ3-2と4bitページ1-0の両方に書き込まれる
   868:   //    0x00d00000  上位バイトは無視され下位バイトが4bitページ3-2と4bitページ1-0の両方に書き込まれる
   869:   //    0x00d80000  上位バイトは無視され下位バイトが4bitページ3-2と4bitページ1-0の両方に書き込まれる
   870:   //
   871:   MMD_GM2 {
   872:     @Override public String toString () {
   873:       return Multilingual.mlnJapanese ? "グラフィックス画面 (メモリモード 2)" : "Graphics Screen (memory mode 2)";
   874:     }
   875:     //ピーク
   876:     @Override protected byte mmdPbs (int a) {
   877:       if ((a & 0x00080001) == 0x00000001) {  //0x00c00000..0x00c7ffff,0x00d00000..0x00d7ffffかつ下位バイト
   878:         a &= 0x00c7fffe;
   879:         return (byte) (MainMemory.mmrM8[0x00080001 + a] << 4 |  //4bitページ1
   880:                        MainMemory.mmrM8[0x00000001 + a]);  //4bitページ0
   881:       } else {  //0x00c80000..0x00cfffff,0x00d80000..0x00dfffffまたは上位バイト
   882:         return 0x00;
   883:       }
   884:     }
   885:     @Override protected int mmdPbz (int a) {
   886:       if ((a & 0x00080001) == 0x00000001) {  //0x00c00000..0x00c7ffff,0x00d00000..0x00d7ffffかつ下位バイト
   887:         a &= 0x00c7fffe;
   888:         return (byte) (MainMemory.mmrM8[0x00080001 + a] << 4 |  //4bitページ1
   889:                        MainMemory.mmrM8[0x00000001 + a]);  //4bitページ0
   890:       } else {  //0x00c80000..0x00cfffff,0x00d80000..0x00dfffffまたは上位バイト
   891:         return 0x00;
   892:       }
   893:     }
   894:     @Override protected int mmdPws (int a) {
   895:       if ((a & 0x00080000) == 0x00000000) {  //0x00c00000..0x00c7ffff,0x00d00000..0x00d7ffff
   896:         a &= 0x00c7fffe;
   897:         return (MainMemory.mmrM8[0x00080001 + a] << 4 |  //4bitページ1
   898:                 MainMemory.mmrM8[0x00000001 + a]);  //4bitページ0
   899:       } else {  //0x00c80000..0x00cfffff,0x00d80000..0x00dfffff
   900:         a &= 0x00c7fffe;
   901:         return (MainMemory.mmrM8[0x00180001 + a] << 4 |  //4bitページ3
   902:                 MainMemory.mmrM8[0x00100001 + a]);  //4bitページ2
   903:       }
   904:     }
   905:     @Override protected int mmdPwz (int a) {
   906:       if ((a & 0x00080000) == 0x00000000) {  //0x00c00000..0x00c7ffff,0x00d00000..0x00d7ffff
   907:         a &= 0x00c7fffe;
   908:         return (MainMemory.mmrM8[0x00080001 + a] << 4 |  //4bitページ1
   909:                 MainMemory.mmrM8[0x00000001 + a]);  //4bitページ0
   910:       } else {  //0x00c80000..0x00cfffff,0x00d80000..0x00dfffff
   911:         a &= 0x00c7fffe;
   912:         return (MainMemory.mmrM8[0x00180001 + a] << 4 |  //4bitページ3
   913:                 MainMemory.mmrM8[0x00100001 + a]);  //4bitページ2
   914:       }
   915:     }
   916:     @Override protected int mmdPls (int a) {
   917:       a &= 0x00d7fffe;
   918:       return (MainMemory.mmrM8[0x00080001 + a] << 20 |  //4bitページ1,3
   919:               MainMemory.mmrM8[0x00000001 + a] << 16 |  //4bitページ0,2
   920:               MainMemory.mmrM8[0x00080003 + a] <<  4 |  //4bitページ1,3
   921:               MainMemory.mmrM8[0x00000003 + a]);  //4bitページ0,2
   922:     }
   923:     //リード
   924:     @Override protected byte mmdRbs (int a) throws M68kException {
   925:        XEiJ.mpuClockTime += XEiJ.busWaitTime.gvram;
   926:        if ((a & 0x00080001) == 0x00000001) {  //0x00c00000..0x00c7ffff,0x00d00000..0x00d7ffffかつ下位バイト
   927:          a &= 0x00c7fffe;
   928:          return (byte) (MainMemory.mmrM8[0x00080001 + a] << 4 |  //4bitページ1
   929:                         MainMemory.mmrM8[0x00000001 + a]);  //4bitページ0
   930:        } else {  //0x00c80000..0x00cfffff,0x00d80000..0x00dfffffまたは上位バイト
   931:          return 0x00;
   932:        }
   933:      }
   934:     @Override protected int mmdRbz (int a) throws M68kException {
   935:        XEiJ.mpuClockTime += XEiJ.busWaitTime.gvram;
   936:        if ((a & 0x00080001) == 0x00000001) {  //0x00c00000..0x00c7ffff,0x00d00000..0x00d7ffffかつ下位バイト
   937:          a &= 0x00c7fffe;
   938:          return (byte) (MainMemory.mmrM8[0x00080001 + a] << 4 |  //4bitページ1
   939:                         MainMemory.mmrM8[0x00000001 + a]);  //4bitページ0
   940:        } else {  //0x00c80000..0x00cfffff,0x00d80000..0x00dfffffまたは上位バイト
   941:          return 0x00;
   942:        }
   943:      }
   944:     @Override protected int mmdRws (int a) throws M68kException {
   945:        XEiJ.mpuClockTime += XEiJ.busWaitTime.gvram;
   946:        if ((a & 0x00080000) == 0x00000000) {  //0x00c00000..0x00c7ffff,0x00d00000..0x00d7ffff
   947:          a &= 0x00c7fffe;
   948:          return (MainMemory.mmrM8[0x00080001 + a] << 4 |  //4bitページ1
   949:                  MainMemory.mmrM8[0x00000001 + a]);  //4bitページ0
   950:        } else {  //0x00c80000..0x00cfffff,0x00d80000..0x00dfffff
   951:          a &= 0x00c7fffe;
   952:          return (MainMemory.mmrM8[0x00180001 + a] << 4 |  //4bitページ3
   953:                  MainMemory.mmrM8[0x00100001 + a]);  //4bitページ2
   954:        }
   955:      }
   956:     @Override protected int mmdRwz (int a) throws M68kException {
   957:        XEiJ.mpuClockTime += XEiJ.busWaitTime.gvram;
   958:        if ((a & 0x00080000) == 0x00000000) {  //0x00c00000..0x00c7ffff,0x00d00000..0x00d7ffff
   959:          a &= 0x00c7fffe;
   960:          return (MainMemory.mmrM8[0x00080001 + a] << 4 |  //4bitページ1
   961:                  MainMemory.mmrM8[0x00000001 + a]);  //4bitページ0
   962:        } else {  //0x00c80000..0x00cfffff,0x00d80000..0x00dfffff
   963:          a &= 0x00c7fffe;
   964:          return (MainMemory.mmrM8[0x00180001 + a] << 4 |  //4bitページ3
   965:                  MainMemory.mmrM8[0x00100001 + a]);  //4bitページ2
   966:        }
   967:      }
   968:     @Override protected int mmdRls (int a) throws M68kException {
   969:        XEiJ.mpuClockTime += XEiJ.busWaitTime.gvram * 2;
   970:        a &= 0x00d7fffe;
   971:        return (MainMemory.mmrM8[0x00080001 + a] << 20 |  //4bitページ1,3
   972:                MainMemory.mmrM8[0x00000001 + a] << 16 |  //4bitページ0,2
   973:                MainMemory.mmrM8[0x00080003 + a] <<  4 |  //4bitページ1,3
   974:                MainMemory.mmrM8[0x00000003 + a]);  //4bitページ0,2
   975:      }
   976:     //ライト
   977:     @Override protected void mmdWb (int a, int d) throws M68kException {
   978:        XEiJ.mpuClockTime += XEiJ.busWaitTime.gvram;
   979:        if ((a & 0x00000001) == 0x00000000) {  //上位バイト
   980:          a &= 0x00c7fffe;
   981:          if (XEiJ.currentMPU < Model.MPU_MC68LC040) {
   982:            MainMemory.mmrM8[0x00180001 + a] = (byte) (d >>> 4 & 15);  //4bitページ3
   983:            MainMemory.mmrM8[0x00100001 + a] = (byte) (d       & 15);  //4bitページ2
   984:          } else {
   985:            MainMemory.mmrM8[0x00180001 + a] = 0;  //4bitページ3
   986:            MainMemory.mmrM8[0x00100001 + a] = 0;  //4bitページ2
   987:          }
   988:          a >>>= 10;
   989:          int y = a - CRTC.crtR13GrYCurr[3] & 511;
   990:          CRTC.crtRasterStamp[y      ] = 0;
   991:          CRTC.crtRasterStamp[y + 512] = 0;
   992:          y = a - CRTC.crtR13GrYCurr[2] & 511;
   993:          CRTC.crtRasterStamp[y      ] = 0;
   994:          CRTC.crtRasterStamp[y + 512] = 0;
   995:        } else {  //下位バイト
   996:          a &= 0x00c7fffe;
   997:          MainMemory.mmrM8[0x00080001 + a] = (byte) (d >>> 4 & 15);  //4bitページ1
   998:          MainMemory.mmrM8[0x00000001 + a] = (byte) (d       & 15);  //4bitページ0
   999:          a >>>= 10;
  1000:          int y = a - CRTC.crtR13GrYCurr[1] & 511;
  1001:          CRTC.crtRasterStamp[y      ] = 0;
  1002:          CRTC.crtRasterStamp[y + 512] = 0;
  1003:          y = a - CRTC.crtR13GrYCurr[0] & 511;
  1004:          CRTC.crtRasterStamp[y      ] = 0;
  1005:          CRTC.crtRasterStamp[y + 512] = 0;
  1006:        }
  1007:      }
  1008:     @Override protected void mmdWw (int a, int d) throws M68kException {
  1009:        XEiJ.mpuClockTime += XEiJ.busWaitTime.gvram;
  1010:        a &= 0x00c7fffe;
  1011:        MainMemory.mmrM8[0x00180001 + a] = MainMemory.mmrM8[0x00080001 + a] = (byte) (d >>> 4 & 15);  //4bitページ1,3
  1012:        MainMemory.mmrM8[0x00100001 + a] = MainMemory.mmrM8[0x00000001 + a] = (byte) (d       & 15);  //4bitページ0,2
  1013:        a >>>= 10;
  1014:        int y = a - CRTC.crtR13GrYCurr[3] & 511;
  1015:        CRTC.crtRasterStamp[y      ] = 0;
  1016:        CRTC.crtRasterStamp[y + 512] = 0;
  1017:        y = a - CRTC.crtR13GrYCurr[2] & 511;
  1018:        CRTC.crtRasterStamp[y      ] = 0;
  1019:        CRTC.crtRasterStamp[y + 512] = 0;
  1020:        y = a - CRTC.crtR13GrYCurr[1] & 511;
  1021:        CRTC.crtRasterStamp[y      ] = 0;
  1022:        CRTC.crtRasterStamp[y + 512] = 0;
  1023:        y = a - CRTC.crtR13GrYCurr[0] & 511;
  1024:        CRTC.crtRasterStamp[y      ] = 0;
  1025:        CRTC.crtRasterStamp[y + 512] = 0;
  1026:      }
  1027:     @Override protected void mmdWl (int a, int d) throws M68kException {
  1028:        XEiJ.mpuClockTime += XEiJ.busWaitTime.gvram * 2;
  1029:        a &= 0x00c7fffe;
  1030:        MainMemory.mmrM8[0x00180001 + a] = MainMemory.mmrM8[0x00080001 + a] = (byte) (d >>> 20 & 15);  //ページ1,3
  1031:        MainMemory.mmrM8[0x00100001 + a] = MainMemory.mmrM8[0x00000001 + a] = (byte) (d >>> 16 & 15);  //ページ0,2
  1032:        MainMemory.mmrM8[0x00180003 + a] = MainMemory.mmrM8[0x00080003 + a] = (byte) (d >>>  4 & 15);  //ページ1,3
  1033:        MainMemory.mmrM8[0x00100003 + a] = MainMemory.mmrM8[0x00000003 + a] = (byte) (d        & 15);  //ページ0,2
  1034:        a >>>= 10;
  1035:        int y = a - CRTC.crtR13GrYCurr[3] & 511;
  1036:        CRTC.crtRasterStamp[y      ] = 0;
  1037:        CRTC.crtRasterStamp[y + 512] = 0;
  1038:        y = a - CRTC.crtR13GrYCurr[2] & 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[0] & 511;
  1045:        CRTC.crtRasterStamp[y      ] = 0;
  1046:        CRTC.crtRasterStamp[y + 512] = 0;
  1047:      }
  1048:   },  //MMD_GM2
  1049: 
  1050:   //--------------------------------------------------------------------------------
  1051:   //MMD_GG0 グラフィックス画面(512ドット65536色)
  1052:   //
  1053:   //  512ドット65536色
  1054:   //                アドレス             アクセス                  格納
  1055:   //    GG0  0x00c00000~0x00c7ffff  fedcba9876543210  ─┬  ............3210
  1056:   //         0x00c80000~0x00cfffff                      ├  ............7654
  1057:   //         0x00d00000~0x00d7ffff                      ├  ............ba98
  1058:   //         0x00d80000~0x00dfffff                      └  ............fedc
  1059:   //
  1060:   MMD_GG0 {
  1061:     @Override public String toString () {
  1062:       return Multilingual.mlnJapanese ? "グラフィックス画面 (512 ドット 65536 色)" : "Graphics Screen (512 dots 65536 colors)";
  1063:     }
  1064:     //ピーク
  1065:     @Override protected byte mmdPbs (int a) {
  1066:       a &= XEiJ.BUS_MOTHER_MASK;
  1067:       a += -(~a & 1) & 0x00100001;
  1068:       return (byte) (MainMemory.mmrM8[a + 0x00080000] << 4 | MainMemory.mmrM8[a]);
  1069:     }
  1070:     @Override protected int mmdPbz (int a) {
  1071:       a &= XEiJ.BUS_MOTHER_MASK;
  1072:       a += -(~a & 1) & 0x00100001;
  1073:       return MainMemory.mmrM8[a + 0x00080000] << 4 | MainMemory.mmrM8[a];
  1074:     }
  1075:     @Override protected int mmdPws (int a) {
  1076:       a &= XEiJ.BUS_MOTHER_MASK;
  1077:       return (short) (MainMemory.mmrM8[a + 0x00180001] << 12 | MainMemory.mmrM8[a + 0x00100001] << 8 | MainMemory.mmrM8[a + 0x00080001] << 4 | MainMemory.mmrM8[a + 1]);
  1078:     }
  1079:     @Override protected int mmdPwz (int a) {
  1080:       a &= XEiJ.BUS_MOTHER_MASK;
  1081:       return MainMemory.mmrM8[a + 0x00180001] << 12 | MainMemory.mmrM8[a + 0x00100001] << 8 | MainMemory.mmrM8[a + 0x00080001] << 4 | MainMemory.mmrM8[a + 1];
  1082:     }
  1083:     @Override protected int mmdPls (int a) {
  1084:       a &= XEiJ.BUS_MOTHER_MASK;
  1085:       return (MainMemory.mmrM8[a + 0x00180001] << 28 | MainMemory.mmrM8[a + 0x00100001] << 24 | MainMemory.mmrM8[a + 0x00080001] << 20 | MainMemory.mmrM8[a + 1] << 16 |
  1086:               MainMemory.mmrM8[a + 0x00180003] << 12 | MainMemory.mmrM8[a + 0x00100003] << 8 | MainMemory.mmrM8[a + 0x00080003] << 4 | MainMemory.mmrM8[a + 3]);
  1087:     }
  1088:     //リード
  1089:     @Override protected byte mmdRbs (int a) throws M68kException {
  1090:        XEiJ.mpuClockTime += XEiJ.busWaitTime.gvram;
  1091:        a &= XEiJ.BUS_MOTHER_MASK;
  1092:        a += -(~a & 1) & 0x00100001;
  1093:        return (byte) (MainMemory.mmrM8[a + 0x00080000] << 4 | MainMemory.mmrM8[a]);
  1094:      }
  1095:     @Override protected int mmdRbz (int a) throws M68kException {
  1096:        XEiJ.mpuClockTime += XEiJ.busWaitTime.gvram;
  1097:        a &= XEiJ.BUS_MOTHER_MASK;
  1098:        a += -(~a & 1) & 0x00100001;
  1099:        return MainMemory.mmrM8[a + 0x00080000] << 4 | MainMemory.mmrM8[a];
  1100:      }
  1101:     @Override protected int mmdRws (int a) throws M68kException {
  1102:        XEiJ.mpuClockTime += XEiJ.busWaitTime.gvram;
  1103:        a &= XEiJ.BUS_MOTHER_MASK;
  1104:        return (short) (MainMemory.mmrM8[a + 0x00180001] << 12 | MainMemory.mmrM8[a + 0x00100001] << 8 | MainMemory.mmrM8[a + 0x00080001] << 4 | MainMemory.mmrM8[a + 1]);
  1105:      }
  1106:     @Override protected int mmdRwz (int a) throws M68kException {
  1107:        XEiJ.mpuClockTime += XEiJ.busWaitTime.gvram;
  1108:        a &= XEiJ.BUS_MOTHER_MASK;
  1109:        return MainMemory.mmrM8[a + 0x00180001] << 12 | MainMemory.mmrM8[a + 0x00100001] << 8 | MainMemory.mmrM8[a + 0x00080001] << 4 | MainMemory.mmrM8[a + 1];
  1110:      }
  1111:     @Override protected int mmdRls (int a) throws M68kException {
  1112:        XEiJ.mpuClockTime += XEiJ.busWaitTime.gvram * 2;
  1113:        a &= XEiJ.BUS_MOTHER_MASK;
  1114:        return (MainMemory.mmrM8[a + 0x00180001] << 28 | MainMemory.mmrM8[a + 0x00100001] << 24 | MainMemory.mmrM8[a + 0x00080001] << 20 | MainMemory.mmrM8[a + 1] << 16 |
  1115:                MainMemory.mmrM8[a + 0x00180003] << 12 | MainMemory.mmrM8[a + 0x00100003] << 8 | MainMemory.mmrM8[a + 0x00080003] << 4 | MainMemory.mmrM8[a + 3]);
  1116:      }
  1117:     //ライト
  1118:     @Override protected void mmdWb (int a, int d) throws M68kException {
  1119:        XEiJ.mpuClockTime += XEiJ.busWaitTime.gvram;
  1120:        a &= XEiJ.BUS_MOTHER_MASK;
  1121:        if (XEiJ.TEST_BIT_0_SHIFT ? a << 31 - 0 >= 0 : (a & 1) == 0) {
  1122:          MainMemory.mmrM8[a + 0x00180001] = (byte) (d << 24  >>> 28);
  1123:          MainMemory.mmrM8[a + 0x00100001] = (byte) (d          & 15);
  1124:          a >>= 10;
  1125:          int y = a - CRTC.crtR13GrYCurr[2] & 511;
  1126:          CRTC.crtRasterStamp[y      ] = 0;
  1127:          CRTC.crtRasterStamp[y + 512] = 0;
  1128:          y = a - CRTC.crtR13GrYCurr[3] & 511;
  1129:          CRTC.crtRasterStamp[y      ] = 0;
  1130:          CRTC.crtRasterStamp[y + 512] = 0;
  1131:        } else {
  1132:          MainMemory.mmrM8[a + 0x00080000] = (byte) (d << 24  >>> 28);
  1133:          MainMemory.mmrM8[a             ] = (byte) (d          & 15);
  1134:          a >>= 10;
  1135:          int y = a - CRTC.crtR13GrYCurr[0] & 511;
  1136:          CRTC.crtRasterStamp[y      ] = 0;
  1137:          CRTC.crtRasterStamp[y + 512] = 0;
  1138:          y = a - CRTC.crtR13GrYCurr[1] & 511;
  1139:          CRTC.crtRasterStamp[y      ] = 0;
  1140:          CRTC.crtRasterStamp[y + 512] = 0;
  1141:        }
  1142:      }
  1143:     @Override protected void mmdWw (int a, int d) throws M68kException {
  1144:        XEiJ.mpuClockTime += XEiJ.busWaitTime.gvram;
  1145:        a &= XEiJ.BUS_MOTHER_MASK;
  1146:        MainMemory.mmrM8[a + 0x00180001] = (byte) ((char) d >>> 12);
  1147:        MainMemory.mmrM8[a + 0x00100001] = (byte) (d << 20  >>> 28);
  1148:        MainMemory.mmrM8[a + 0x00080001] = (byte) (d << 24  >>> 28);
  1149:        MainMemory.mmrM8[a + 0x00000001] = (byte) (d          & 15);
  1150:        a >>= 10;
  1151:        int y = a - CRTC.crtR13GrYCurr[0] & 511;
  1152:        CRTC.crtRasterStamp[y      ] = 0;
  1153:        CRTC.crtRasterStamp[y + 512] = 0;
  1154:        y = a - CRTC.crtR13GrYCurr[1] & 511;
  1155:        CRTC.crtRasterStamp[y      ] = 0;
  1156:        CRTC.crtRasterStamp[y + 512] = 0;
  1157:        y = a - CRTC.crtR13GrYCurr[2] & 511;
  1158:        CRTC.crtRasterStamp[y      ] = 0;
  1159:        CRTC.crtRasterStamp[y + 512] = 0;
  1160:        y = a - CRTC.crtR13GrYCurr[3] & 511;
  1161:        CRTC.crtRasterStamp[y      ] = 0;
  1162:        CRTC.crtRasterStamp[y + 512] = 0;
  1163:      }
  1164:     @Override protected void mmdWl (int a, int d) throws M68kException {
  1165:        XEiJ.mpuClockTime += XEiJ.busWaitTime.gvram * 2;
  1166:        a &= XEiJ.BUS_MOTHER_MASK;
  1167:        MainMemory.mmrM8[a + 0x00180001] = (byte) (d        >>> 28);
  1168:        MainMemory.mmrM8[a + 0x00100001] = (byte) (d <<  4  >>> 28);
  1169:        MainMemory.mmrM8[a + 0x00080001] = (byte) (d <<  8  >>> 28);
  1170:        MainMemory.mmrM8[a + 0x00000001] = (byte) (d << 12  >>> 28);
  1171:        MainMemory.mmrM8[a + 0x00180003] = (byte) ((char) d >>> 12);
  1172:        MainMemory.mmrM8[a + 0x00100003] = (byte) (d << 20  >>> 28);
  1173:        MainMemory.mmrM8[a + 0x00080003] = (byte) (d << 24  >>> 28);
  1174:        MainMemory.mmrM8[a + 0x00000003] = (byte) (d          & 15);
  1175:        a >>= 10;
  1176:        int y = a - CRTC.crtR13GrYCurr[0] & 511;
  1177:        CRTC.crtRasterStamp[y      ] = 0;
  1178:        CRTC.crtRasterStamp[y + 512] = 0;
  1179:        y = a - CRTC.crtR13GrYCurr[1] & 511;
  1180:        CRTC.crtRasterStamp[y      ] = 0;
  1181:        CRTC.crtRasterStamp[y + 512] = 0;
  1182:        y = a - CRTC.crtR13GrYCurr[2] & 511;
  1183:        CRTC.crtRasterStamp[y      ] = 0;
  1184:        CRTC.crtRasterStamp[y + 512] = 0;
  1185:        y = a - CRTC.crtR13GrYCurr[3] & 511;
  1186:        CRTC.crtRasterStamp[y      ] = 0;
  1187:        CRTC.crtRasterStamp[y + 512] = 0;
  1188:      }
  1189:   },  //MMD_GG0
  1190: 
  1191:   //--------------------------------------------------------------------------------
  1192:   //MMD_GH0 グラフィックス画面(1024ドット16色)
  1193:   //
  1194:   //  参照アドレス
  1195:   //    0b00000000_110Yyyyy_yyyyyXxx_xxxxxxx?
  1196:   //    +--------------------------+--------------------------+
  1197:   //    | 0x00c00000 .. 0x00c003ff | 0x00c00400 .. 0x00c007ff |
  1198:   //    | 0x00c00800    0x00c00bff | 0x00c00c00    0x00c00fff |
  1199:   //    |      :             :     |      :             :     |
  1200:   //    | 0x00cff000    0x00cff3ff | 0x00cff400    0x00cff7ff |
  1201:   //    | 0x00cff800 .. 0x00cffbff | 0x00cffc00 .. 0x00cfffff |
  1202:   //    +--------------------------+--------------------------+
  1203:   //    | 0x00d00000 .. 0x00d003ff | 0x00d00400 .. 0x00d007ff |
  1204:   //    | 0x00d00800    0x00d00bff | 0x00d00c00    0x00d00fff |
  1205:   //    |      :             :     |      :             :     |
  1206:   //    | 0x00dff000    0x00dff3ff | 0x00dff400    0x00dff7ff |
  1207:   //    | 0x00dff800 .. 0x00dffbff | 0x00dffc00 .. 0x00dfffff |
  1208:   //    +--------------------------+--------------------------+
  1209:   //
  1210:   //  格納アドレス
  1211:   //    0b00000000_110YXyyy_yyyyyyxx_xxxxxxx?
  1212:   //    +--------------------------+--------------------------+
  1213:   //    | 0x00c00000 .. 0x00c003ff | 0x00c80000 .. 0x00c803ff |
  1214:   //    | 0x00c00400    0x00c007ff | 0x00c80400    0x00c807ff |
  1215:   //    |      :     G0      :     |      :     G1      :     |
  1216:   //    | 0x00c7f800    0x00c7fbff | 0x00cff800    0x00cffbff |
  1217:   //    | 0x00c7fc00 .. 0x00c7ffff | 0x00cffc00 .. 0x00cfffff |
  1218:   //    +--------------------------+--------------------------+
  1219:   //    | 0x00d00000 .. 0x00d003ff | 0x00d80000 .. 0x00d803ff |
  1220:   //    | 0x00d00400    0x00d007ff | 0x00d80400    0x00d807ff |
  1221:   //    |      :     G2      :     |      :     G3      :     |
  1222:   //    | 0x00d7f800    0x00d7fbff | 0x00dff800    0x00dffbff |
  1223:   //    | 0x00d7fc00 .. 0x00d7ffff | 0x00dffc00 .. 0x00dfffff |
  1224:   //    +--------------------------+--------------------------+
  1225:   //
  1226:   //    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@;}"
  1227:   //    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@;}"
  1228:   //      0x00c00000  0x00c003ff  0x00c80000  0x00c803ff
  1229:   //      0x00c00400  0x00c007ff  0x00c80400  0x00c807ff
  1230:   //      0x00c7f800  0x00c7fbff  0x00cff800  0x00cffbff
  1231:   //      0x00c7fc00  0x00c7ffff  0x00cffc00  0x00cfffff
  1232:   //      0x00d00000  0x00d003ff  0x00d80000  0x00d803ff
  1233:   //      0x00d00400  0x00d007ff  0x00d80400  0x00d807ff
  1234:   //      0x00d7f800  0x00d7fbff  0x00dff800  0x00dffbff
  1235:   //      0x00d7fc00  0x00d7ffff  0x00dffc00  0x00dfffff
  1236:   //
  1237:   MMD_GH0 {
  1238:     @Override public String toString () {
  1239:       return Multilingual.mlnJapanese ? "グラフィックス画面 (1024 ドット 16 色)" : "Graphics Screen (1024 dots 16 colors)";
  1240:     }
  1241:     //ピーク
  1242:     @Override protected byte mmdPbs (int a) {
  1243:       int b0 = (a & 0x00c00000 + (1 << 20) + 1023) + (a << 9 & 1 << 19) + (a >>> 1 & 511 << 10);
  1244:       return MainMemory.mmrM8[b0];
  1245:     }
  1246:     @Override protected int mmdPbz (int a) {
  1247:       int b0 = (a & 0x00c00000 + (1 << 20) + 1023) + (a << 9 & 1 << 19) + (a >>> 1 & 511 << 10);
  1248:       return MainMemory.mmrM8[b0];
  1249:     }
  1250:     @Override protected int mmdPws (int a) {
  1251:       int b0 = (a & 0x00c00000 + (1 << 20) + 1023) + (a << 9 & 1 << 19) + (a >>> 1 & 511 << 10);
  1252:       return MainMemory.mmrM8[b0 + 1];
  1253:     }
  1254:     @Override protected int mmdPwz (int a) {
  1255:       int b0 = (a & 0x00c00000 + (1 << 20) + 1023) + (a << 9 & 1 << 19) + (a >>> 1 & 511 << 10);
  1256:       return MainMemory.mmrM8[b0 + 1];
  1257:     }
  1258:     @Override protected int mmdPls (int a) {
  1259:       //4bitページを跨ぐ場合があることに注意
  1260:       int b0 = (a & 0x00c00000 + (1 << 20) + 1023) + (a << 9 & 1 << 19) + (a >>> 1 & 511 << 10);
  1261:       a += 2;
  1262:       int b2 = (a & 0x00c00000 + (1 << 20) + 1023) + (a << 9 & 1 << 19) + (a >>> 1 & 511 << 10);
  1263:       return MainMemory.mmrM8[b0 + 1] << 16 | MainMemory.mmrM8[b2 + 1];
  1264:     }
  1265:     //リード
  1266:     @Override protected byte mmdRbs (int a) throws M68kException {
  1267:        XEiJ.mpuClockTime += XEiJ.busWaitTime.gvram;
  1268:        int b0 = (a & 0x00c00000 + (1 << 20) + 1023) + (a << 9 & 1 << 19) + (a >>> 1 & 511 << 10);
  1269:        return MainMemory.mmrM8[b0];
  1270:      }
  1271:     @Override protected int mmdRbz (int a) throws M68kException {
  1272:        XEiJ.mpuClockTime += XEiJ.busWaitTime.gvram;
  1273:        int b0 = (a & 0x00c00000 + (1 << 20) + 1023) + (a << 9 & 1 << 19) + (a >>> 1 & 511 << 10);
  1274:        return MainMemory.mmrM8[b0];
  1275:      }
  1276:     @Override protected int mmdRws (int a) throws M68kException {
  1277:        XEiJ.mpuClockTime += XEiJ.busWaitTime.gvram;
  1278:        int b0 = (a & 0x00c00000 + (1 << 20) + 1023) + (a << 9 & 1 << 19) + (a >>> 1 & 511 << 10);
  1279:        return MainMemory.mmrM8[b0 + 1];
  1280:      }
  1281:     @Override protected int mmdRwz (int a) throws M68kException {
  1282:        XEiJ.mpuClockTime += XEiJ.busWaitTime.gvram;
  1283:        int b0 = (a & 0x00c00000 + (1 << 20) + 1023) + (a << 9 & 1 << 19) + (a >>> 1 & 511 << 10);
  1284:        return MainMemory.mmrM8[b0 + 1];
  1285:      }
  1286:     @Override protected int mmdRls (int a) throws M68kException {
  1287:        XEiJ.mpuClockTime += XEiJ.busWaitTime.gvram * 2;
  1288:        //4bitページを跨ぐ場合があることに注意
  1289:        int b0 = (a & 0x00c00000 + (1 << 20) + 1023) + (a << 9 & 1 << 19) + (a >>> 1 & 511 << 10);
  1290:        a += 2;
  1291:        int b2 = (a & 0x00c00000 + (1 << 20) + 1023) + (a << 9 & 1 << 19) + (a >>> 1 & 511 << 10);
  1292:        return MainMemory.mmrM8[b0 + 1] << 16 | MainMemory.mmrM8[b2 + 1];
  1293:      }
  1294:     //ライト
  1295:     @Override protected void mmdWb (int a, int d) throws M68kException {
  1296:        XEiJ.mpuClockTime += XEiJ.busWaitTime.gvram;
  1297:        if ((a & 1) != 0) {
  1298:          CRTC.crtRasterStamp[(a >> 11) - CRTC.crtR13GrYCurr[0] & 1023] = 0;
  1299:          int b0 = (a & 0x00c00000 + (1 << 20) + 1023) + (a << 9 & 1 << 19) + (a >>> 1 & 511 << 10);
  1300:          MainMemory.mmrM8[b0] = (byte) (d & 15);
  1301:        }
  1302:      }
  1303:     @Override protected void mmdWw (int a, int d) throws M68kException {
  1304:        XEiJ.mpuClockTime += XEiJ.busWaitTime.gvram;
  1305:        CRTC.crtRasterStamp[(a >> 11) - CRTC.crtR13GrYCurr[0] & 1023] = 0;
  1306:        int b0 = (a & 0x00c00000 + (1 << 20) + 1023) + (a << 9 & 1 << 19) + (a >>> 1 & 511 << 10);
  1307:        MainMemory.mmrM8[b0 + 1] = (byte) (d & 15);
  1308:      }
  1309:     @Override protected void mmdWl (int a, int d) throws M68kException {
  1310:        XEiJ.mpuClockTime += XEiJ.busWaitTime.gvram * 2;
  1311:        CRTC.crtRasterStamp[(a >> 11) - CRTC.crtR13GrYCurr[0] & 1023] = 0;
  1312:        //4bitページを跨ぐ場合があることに注意
  1313:        int b0 = (a & 0x00c00000 + (1 << 20) + 1023) + (a << 9 & 1 << 19) + (a >>> 1 & 511 << 10);
  1314:        a += 2;
  1315:        int b2 = (a & 0x00c00000 + (1 << 20) + 1023) + (a << 9 & 1 << 19) + (a >>> 1 & 511 << 10);
  1316:        MainMemory.mmrM8[b0 + 1] = (byte) (d >>> 16 & 15);
  1317:        MainMemory.mmrM8[b2 + 1] = (byte) (d & 15);
  1318:      }
  1319:   },  //MMD_GH0
  1320: 
  1321:   //--------------------------------------------------------------------------------
  1322:   //MMD_GI0 グラフィックス画面(1024ドット256色)
  1323:   //
  1324:   //  参照アドレスと格納アドレスはGH0と同じ
  1325:   //
  1326:   MMD_GI0 {
  1327:     @Override public String toString () {
  1328:       return Multilingual.mlnJapanese ? "グラフィックス画面 (1024 ドット 256 色)" : "Graphics Screen (1024 dots 256 colors)";
  1329:     }
  1330:     //ピーク
  1331:     @Override protected byte mmdPbs (int a) {
  1332:       int b0 = XEiJ.BUS_MODIFIED_256_PAGE + (a & (1 << 20) + 1023) + (a << 9 & 1 << 19) + (a >>> 1 & 511 << 10);
  1333:       return MainMemory.mmrM8[b0];
  1334:     }
  1335:     @Override protected int mmdPbz (int a) {
  1336:       int b0 = XEiJ.BUS_MODIFIED_256_PAGE + (a & (1 << 20) + 1023) + (a << 9 & 1 << 19) + (a >>> 1 & 511 << 10);
  1337:       return MainMemory.mmrM8[b0] & 0xff;
  1338:     }
  1339:     @Override protected int mmdPws (int a) {
  1340:       int b0 = XEiJ.BUS_MODIFIED_256_PAGE + (a & (1 << 20) + 1023) + (a << 9 & 1 << 19) + (a >>> 1 & 511 << 10);
  1341:       return MainMemory.mmrM8[b0 + 1] & 0xff;
  1342:     }
  1343:     @Override protected int mmdPwz (int a) {
  1344:       int b0 = XEiJ.BUS_MODIFIED_256_PAGE + (a & (1 << 20) + 1023) + (a << 9 & 1 << 19) + (a >>> 1 & 511 << 10);
  1345:       return MainMemory.mmrM8[b0 + 1] & 0xff;
  1346:     }
  1347:     @Override protected int mmdPls (int a) {
  1348:       //4bitページを跨ぐ場合があることに注意
  1349:       int b0 = XEiJ.BUS_MODIFIED_256_PAGE + (a & (1 << 20) + 1023) + (a << 9 & 1 << 19) + (a >>> 1 & 511 << 10);
  1350:       a += 2;
  1351:       int b2 = XEiJ.BUS_MODIFIED_256_PAGE + (a & (1 << 20) + 1023) + (a << 9 & 1 << 19) + (a >>> 1 & 511 << 10);
  1352:       return (MainMemory.mmrM8[b0 + 1] & 0xff) << 16 | MainMemory.mmrM8[b2 + 1] & 0xff;
  1353:     }
  1354:     //リード
  1355:     @Override protected byte mmdRbs (int a) throws M68kException {
  1356:        XEiJ.mpuClockTime += XEiJ.busWaitTime.gvram;
  1357:        int b0 = XEiJ.BUS_MODIFIED_256_PAGE + (a & (1 << 20) + 1023) + (a << 9 & 1 << 19) + (a >>> 1 & 511 << 10);
  1358:        return MainMemory.mmrM8[b0];
  1359:      }
  1360:     @Override protected int mmdRbz (int a) throws M68kException {
  1361:        XEiJ.mpuClockTime += XEiJ.busWaitTime.gvram;
  1362:        int b0 = XEiJ.BUS_MODIFIED_256_PAGE + (a & (1 << 20) + 1023) + (a << 9 & 1 << 19) + (a >>> 1 & 511 << 10);
  1363:        return MainMemory.mmrM8[b0] & 0xff;
  1364:      }
  1365:     @Override protected int mmdRws (int a) throws M68kException {
  1366:        XEiJ.mpuClockTime += XEiJ.busWaitTime.gvram;
  1367:        int b0 = XEiJ.BUS_MODIFIED_256_PAGE + (a & (1 << 20) + 1023) + (a << 9 & 1 << 19) + (a >>> 1 & 511 << 10);
  1368:        return MainMemory.mmrM8[b0 + 1] & 0xff;
  1369:      }
  1370:     @Override protected int mmdRwz (int a) throws M68kException {
  1371:        XEiJ.mpuClockTime += XEiJ.busWaitTime.gvram;
  1372:        int b0 = XEiJ.BUS_MODIFIED_256_PAGE + (a & (1 << 20) + 1023) + (a << 9 & 1 << 19) + (a >>> 1 & 511 << 10);
  1373:        return MainMemory.mmrM8[b0 + 1] & 0xff;
  1374:      }
  1375:     @Override protected int mmdRls (int a) throws M68kException {
  1376:        XEiJ.mpuClockTime += XEiJ.busWaitTime.gvram * 2;
  1377:        //4bitページを跨ぐ場合があることに注意
  1378:        int b0 = XEiJ.BUS_MODIFIED_256_PAGE + (a & (1 << 20) + 1023) + (a << 9 & 1 << 19) + (a >>> 1 & 511 << 10);
  1379:        a += 2;
  1380:        int b2 = XEiJ.BUS_MODIFIED_256_PAGE + (a & (1 << 20) + 1023) + (a << 9 & 1 << 19) + (a >>> 1 & 511 << 10);
  1381:        return (MainMemory.mmrM8[b0 + 1] & 0xff) << 16 | MainMemory.mmrM8[b2 + 1] & 0xff;
  1382:      }
  1383:     //ライト
  1384:     @Override protected void mmdWb (int a, int d) throws M68kException {
  1385:        XEiJ.mpuClockTime += XEiJ.busWaitTime.gvram;
  1386:        if ((a & 1) != 0) {
  1387:          CRTC.crtRasterStamp[(a >> 11) - CRTC.crtR13GrYCurr[0] & 1023] = 0;
  1388:          int b0 = XEiJ.BUS_MODIFIED_256_PAGE + (a & (1 << 20) + 1023) + (a << 9 & 1 << 19) + (a >>> 1 & 511 << 10);
  1389:          MainMemory.mmrM8[b0] = (byte) d;
  1390:        }
  1391:      }
  1392:     @Override protected void mmdWw (int a, int d) throws M68kException {
  1393:        XEiJ.mpuClockTime += XEiJ.busWaitTime.gvram;
  1394:        CRTC.crtRasterStamp[(a >> 11) - CRTC.crtR13GrYCurr[0] & 1023] = 0;
  1395:        int b0 = XEiJ.BUS_MODIFIED_256_PAGE + (a & (1 << 20) + 1023) + (a << 9 & 1 << 19) + (a >>> 1 & 511 << 10);
  1396:        MainMemory.mmrM8[b0 + 1] = (byte) d;
  1397:      }
  1398:     @Override protected void mmdWl (int a, int d) throws M68kException {
  1399:        XEiJ.mpuClockTime += XEiJ.busWaitTime.gvram * 2;
  1400:        CRTC.crtRasterStamp[(a >> 11) - CRTC.crtR13GrYCurr[0] & 1023] = 0;
  1401:        //4bitページを跨ぐ場合があることに注意
  1402:        int b0 = XEiJ.BUS_MODIFIED_256_PAGE + (a & (1 << 20) + 1023) + (a << 9 & 1 << 19) + (a >>> 1 & 511 << 10);
  1403:        a += 2;
  1404:        int b2 = XEiJ.BUS_MODIFIED_256_PAGE + (a & (1 << 20) + 1023) + (a << 9 & 1 << 19) + (a >>> 1 & 511 << 10);
  1405:        MainMemory.mmrM8[b0 + 1] = (byte) (d >>> 16);
  1406:        MainMemory.mmrM8[b2 + 1] = (byte) d;
  1407:      }
  1408:   },  //MMD_GI0
  1409: 
  1410:   //--------------------------------------------------------------------------------
  1411:   //MMD_GJ0 グラフィックス画面(1024ドット65536色)
  1412:   //
  1413:   //  参照アドレスと格納アドレスはGH0と同じ
  1414:   //
  1415:   MMD_GJ0 {
  1416:     @Override public String toString () {
  1417:       return Multilingual.mlnJapanese ? "グラフィックス画面 (1024 ドット 65536 色)" : "Graphics Screen (1024 dots 65536 colors)";
  1418:     }
  1419:     //ピーク
  1420:     @Override protected byte mmdPbs (int a) {
  1421:       int b0 = XEiJ.BUS_MODIFIED_65536_PAGE + (a & (1 << 20) + 1023) + (a << 9 & 1 << 19) + (a >>> 1 & 511 << 10);
  1422:       return MainMemory.mmrM8[b0];
  1423:     }
  1424:     @Override protected int mmdPbz (int a) {
  1425:       int b0 = XEiJ.BUS_MODIFIED_65536_PAGE + (a & (1 << 20) + 1023) + (a << 9 & 1 << 19) + (a >>> 1 & 511 << 10);
  1426:       return MainMemory.mmrM8[b0] & 0xff;
  1427:     }
  1428:     @Override protected int mmdPws (int a) {
  1429:       int b0 = XEiJ.BUS_MODIFIED_65536_PAGE + (a & (1 << 20) + 1023) + (a << 9 & 1 << 19) + (a >>> 1 & 511 << 10);
  1430:       return MainMemory.mmrM8[b0] << 8 | (MainMemory.mmrM8[b0 + 1] & 0xff);
  1431:     }
  1432:     @Override protected int mmdPwz (int a) {
  1433:       int b0 = XEiJ.BUS_MODIFIED_65536_PAGE + (a & (1 << 20) + 1023) + (a << 9 & 1 << 19) + (a >>> 1 & 511 << 10);
  1434:       return (char) (MainMemory.mmrM8[b0] << 8 | (MainMemory.mmrM8[b0 + 1] & 0xff));
  1435:     }
  1436:     @Override protected int mmdPls (int a) {
  1437:        //4bitページを跨ぐ場合があることに注意
  1438:       int b0 = XEiJ.BUS_MODIFIED_65536_PAGE + (a & (1 << 20) + 1023) + (a << 9 & 1 << 19) + (a >>> 1 & 511 << 10);
  1439:       a += 2;
  1440:       int b2 = XEiJ.BUS_MODIFIED_65536_PAGE + (a & (1 << 20) + 1023) + (a << 9 & 1 << 19) + (a >>> 1 & 511 << 10);
  1441:       return (MainMemory.mmrM8[b0] << 24 | (MainMemory.mmrM8[b0 + 1] & 0xff) << 16 |
  1442:               (char) (MainMemory.mmrM8[b2] << 8 | (MainMemory.mmrM8[b2 + 1] & 0xff)));
  1443:     }
  1444:     //リード
  1445:     @Override protected byte mmdRbs (int a) throws M68kException {
  1446:        XEiJ.mpuClockTime += XEiJ.busWaitTime.gvram;
  1447:        return MainMemory.mmrM8[XEiJ.BUS_MODIFIED_65536_PAGE + (a & (1 << 20) + 1023) + (a << 9 & 1 << 19) + (a >>> 1 & 511 << 10)];
  1448:      }
  1449:     @Override protected int mmdRbz (int a) throws M68kException {
  1450:        XEiJ.mpuClockTime += XEiJ.busWaitTime.gvram;
  1451:        return MainMemory.mmrM8[XEiJ.BUS_MODIFIED_65536_PAGE + (a & (1 << 20) + 1023) + (a << 9 & 1 << 19) + (a >>> 1 & 511 << 10)] & 0xff;
  1452:      }
  1453:     @Override protected int mmdRws (int a) throws M68kException {
  1454:        XEiJ.mpuClockTime += XEiJ.busWaitTime.gvram;
  1455:        int b0 = XEiJ.BUS_MODIFIED_65536_PAGE + (a & (1 << 20) + 1023) + (a << 9 & 1 << 19) + (a >>> 1 & 511 << 10);
  1456:        return MainMemory.mmrM8[b0] << 8 | (MainMemory.mmrM8[b0 + 1] & 0xff);
  1457:      }
  1458:     @Override protected int mmdRwz (int a) throws M68kException {
  1459:        XEiJ.mpuClockTime += XEiJ.busWaitTime.gvram;
  1460:        int b0 = XEiJ.BUS_MODIFIED_65536_PAGE + (a & (1 << 20) + 1023) + (a << 9 & 1 << 19) + (a >>> 1 & 511 << 10);
  1461:        return (char) (MainMemory.mmrM8[b0] << 8 | (MainMemory.mmrM8[b0 + 1] & 0xff));
  1462:      }
  1463:     @Override protected int mmdRls (int a) throws M68kException {
  1464:        XEiJ.mpuClockTime += XEiJ.busWaitTime.gvram * 2;
  1465:        //4bitページを跨ぐ場合があることに注意
  1466:        int b0 = XEiJ.BUS_MODIFIED_65536_PAGE + (a & (1 << 20) + 1023) + (a << 9 & 1 << 19) + (a >>> 1 & 511 << 10);
  1467:        a += 2;
  1468:        int b2 = XEiJ.BUS_MODIFIED_65536_PAGE + (a & (1 << 20) + 1023) + (a << 9 & 1 << 19) + (a >>> 1 & 511 << 10);
  1469:        return (MainMemory.mmrM8[b0] << 24 | (MainMemory.mmrM8[b0 + 1] & 0xff) << 16 |
  1470:                (char) (MainMemory.mmrM8[b2] << 8 | (MainMemory.mmrM8[b2 + 1] & 0xff)));
  1471:      }
  1472:     //ライト
  1473:     @Override protected void mmdWb (int a, int d) throws M68kException {
  1474:        XEiJ.mpuClockTime += XEiJ.busWaitTime.gvram;
  1475:        if ((a & 1) != 0) {
  1476:          CRTC.crtRasterStamp[(a >> 11) - CRTC.crtR13GrYCurr[0] & 1023] = 0;
  1477:          MainMemory.mmrM8[XEiJ.BUS_MODIFIED_65536_PAGE + (a & (1 << 20) + 1023) + (a << 9 & 1 << 19) + (a >>> 1 & 511 << 10)] = (byte) d;
  1478:        }
  1479:      }
  1480:     @Override protected void mmdWw (int a, int d) throws M68kException {
  1481:        XEiJ.mpuClockTime += XEiJ.busWaitTime.gvram;
  1482:        CRTC.crtRasterStamp[(a >> 11) - CRTC.crtR13GrYCurr[0] & 1023] = 0;
  1483:        int b0 = XEiJ.BUS_MODIFIED_65536_PAGE + (a & (1 << 20) + 1023) + (a << 9 & 1 << 19) + (a >>> 1 & 511 << 10);
  1484:        MainMemory.mmrM8[b0] = (byte) (d >> 8);
  1485:        MainMemory.mmrM8[b0 + 1] = (byte) d;
  1486:      }
  1487:     @Override protected void mmdWl (int a, int d) throws M68kException {
  1488:        XEiJ.mpuClockTime += XEiJ.busWaitTime.gvram * 2;
  1489:        CRTC.crtRasterStamp[(a >> 11) - CRTC.crtR13GrYCurr[0] & 1023] = 0;
  1490:        //4bitページを跨ぐ場合があることに注意
  1491:        int b0 = XEiJ.BUS_MODIFIED_65536_PAGE + (a & (1 << 20) + 1023) + (a << 9 & 1 << 19) + (a >>> 1 & 511 << 10);
  1492:        a += 2;
  1493:        int b2 = XEiJ.BUS_MODIFIED_65536_PAGE + (a & (1 << 20) + 1023) + (a << 9 & 1 << 19) + (a >>> 1 & 511 << 10);
  1494:        MainMemory.mmrM8[b0] = (byte) (d >>> 24);
  1495:        MainMemory.mmrM8[b0 + 1] = (byte) (d >>> 16);
  1496:        MainMemory.mmrM8[b2] = (byte) (d >>> 8);
  1497:        MainMemory.mmrM8[b2 + 1] = (byte) d;
  1498:      }
  1499:   },  //MMD_GJ0
  1500: 
  1501:   //--------------------------------------------------------------------------------
  1502:   //MMD_TXT テキスト画面
  1503:   MMD_TXT {
  1504:     @Override public String toString () {
  1505:       return Multilingual.mlnJapanese ? "テキスト画面" : "Text Screen";
  1506:     }
  1507:     //ピーク
  1508:     @Override protected byte mmdPbs (int a) {
  1509:       a &= XEiJ.BUS_MOTHER_MASK;
  1510:       return MainMemory.mmrM8[a];
  1511:     }
  1512:     @Override protected int mmdPbz (int a) {
  1513:       a &= XEiJ.BUS_MOTHER_MASK;
  1514:       return MainMemory.mmrM8[a] & 0xff;
  1515:     }
  1516:     @Override protected int mmdPws (int a) {
  1517:       a &= XEiJ.BUS_MOTHER_MASK;
  1518:       if (MainMemory.MMR_USE_BYTE_BUFFER) {
  1519:         return MainMemory.mmrBuffer.getShort (a);
  1520:       } else {
  1521:         return MainMemory.mmrM8[a] << 8 | (MainMemory.mmrM8[a + 1] & 0xff);
  1522:       }
  1523:     }
  1524:     @Override protected int mmdPwz (int a) {
  1525:       a &= XEiJ.BUS_MOTHER_MASK;
  1526:       if (MainMemory.MMR_USE_BYTE_BUFFER) {
  1527:         return MainMemory.mmrBuffer.getChar (a);
  1528:       } else {
  1529:         return (char) (MainMemory.mmrM8[a] << 8 | (MainMemory.mmrM8[a + 1] & 0xff));
  1530:       }
  1531:     }
  1532:     @Override protected int mmdPls (int a) {
  1533:       a &= XEiJ.BUS_MOTHER_MASK;
  1534:       if (MainMemory.MMR_USE_BYTE_BUFFER) {
  1535:         return MainMemory.mmrBuffer.getInt (a);
  1536:       } else {
  1537:         return MainMemory.mmrM8[a] << 24 | (MainMemory.mmrM8[a + 1] & 0xff) << 16 | (char) (MainMemory.mmrM8[a + 2] << 8 | (MainMemory.mmrM8[a + 3] & 0xff));
  1538:       }
  1539:     }
  1540:     //リード
  1541:     @Override protected byte mmdRbs (int a) throws M68kException {
  1542:        XEiJ.mpuClockTime += XEiJ.busWaitTime.tvram;
  1543:        a &= XEiJ.BUS_MOTHER_MASK;
  1544:        return MainMemory.mmrM8[a];
  1545:      }
  1546:     @Override protected int mmdRbz (int a) throws M68kException {
  1547:        XEiJ.mpuClockTime += XEiJ.busWaitTime.tvram;
  1548:        a &= XEiJ.BUS_MOTHER_MASK;
  1549:        return MainMemory.mmrM8[a] & 0xff;
  1550:      }
  1551:     @Override protected int mmdRws (int a) throws M68kException {
  1552:        XEiJ.mpuClockTime += XEiJ.busWaitTime.tvram;
  1553:        a &= XEiJ.BUS_MOTHER_MASK;
  1554:        if (MainMemory.MMR_USE_BYTE_BUFFER) {
  1555:          return MainMemory.mmrBuffer.getShort (a);
  1556:        } else {
  1557:          return MainMemory.mmrM8[a] << 8 | (MainMemory.mmrM8[a + 1] & 0xff);
  1558:        }
  1559:      }
  1560:     @Override protected int mmdRwz (int a) throws M68kException {
  1561:        XEiJ.mpuClockTime += XEiJ.busWaitTime.tvram;
  1562:        a &= XEiJ.BUS_MOTHER_MASK;
  1563:        if (MainMemory.MMR_USE_BYTE_BUFFER) {
  1564:          return MainMemory.mmrBuffer.getChar (a);
  1565:        } else {
  1566:          return (char) (MainMemory.mmrM8[a] << 8 | (MainMemory.mmrM8[a + 1] & 0xff));
  1567:        }
  1568:      }
  1569:     @Override protected int mmdRls (int a) throws M68kException {
  1570:        XEiJ.mpuClockTime += XEiJ.busWaitTime.tvram * 2;
  1571:        a &= XEiJ.BUS_MOTHER_MASK;
  1572:        if (MainMemory.MMR_USE_BYTE_BUFFER) {
  1573:          return MainMemory.mmrBuffer.getInt (a);
  1574:        } else {
  1575:          return MainMemory.mmrM8[a] << 24 | (MainMemory.mmrM8[a + 1] & 0xff) << 16 | (char) (MainMemory.mmrM8[a + 2] << 8 | (MainMemory.mmrM8[a + 3] & 0xff));
  1576:        }
  1577:      }
  1578:     //ライト
  1579:     @Override protected void mmdWb (int a, int d) throws M68kException {
  1580:        XEiJ.mpuClockTime += XEiJ.busWaitTime.tvram;
  1581:        a &= XEiJ.BUS_MOTHER_MASK;
  1582:        int x;  //マスク
  1583:        if (CRTC.crtSimAccess) {  //同時アクセスあり
  1584:          a &= 0x00e1ffff;
  1585:          if (CRTC.crtBitMask) {  //同時アクセスあり,ビットマスクあり
  1586:            d &= ~(x = CRTC.crtR23Mask >> ((~a & 1) << 3));
  1587:            if (CRTC.crtSimPlane0) {
  1588:              MainMemory.mmrM8[a             ] = (byte) (MainMemory.mmrM8[a             ] & x | d);
  1589:            }
  1590:            if (CRTC.crtSimPlane1) {
  1591:              MainMemory.mmrM8[a + 0x00020000] = (byte) (MainMemory.mmrM8[a + 0x00020000] & x | d);
  1592:            }
  1593:            if (CRTC.crtSimPlane2) {
  1594:              MainMemory.mmrM8[a + 0x00040000] = (byte) (MainMemory.mmrM8[a + 0x00040000] & x | d);
  1595:            }
  1596:            if (CRTC.crtSimPlane3) {
  1597:              MainMemory.mmrM8[a + 0x00060000] = (byte) (MainMemory.mmrM8[a + 0x00060000] & x | d);
  1598:            }
  1599:          } else {  //同時アクセスあり,ビットマスクなし
  1600:            if (CRTC.crtSimPlane0) {
  1601:              MainMemory.mmrM8[a             ] = (byte) d;
  1602:            }
  1603:            if (CRTC.crtSimPlane1) {
  1604:              MainMemory.mmrM8[a + 0x00020000] = (byte) d;
  1605:            }
  1606:            if (CRTC.crtSimPlane2) {
  1607:              MainMemory.mmrM8[a + 0x00040000] = (byte) d;
  1608:            }
  1609:            if (CRTC.crtSimPlane3) {
  1610:              MainMemory.mmrM8[a + 0x00060000] = (byte) d;
  1611:            }
  1612:          }
  1613:        } else if (CRTC.crtBitMask) {  //同時アクセスなし,ビットマスクあり
  1614:          x = CRTC.crtR23Mask >> ((~a & 1) << 3);
  1615:          MainMemory.mmrM8[a] = (byte) (MainMemory.mmrM8[a] & x | d & ~x);
  1616:        } else {  //同時アクセスなし,ビットマスクなし
  1617:          MainMemory.mmrM8[a] = (byte) d;
  1618:        }
  1619:        //同時アクセスやビットマスクで1ピクセルも書き換えなくても更新することになる
  1620:        a = ((a & 0x0001ffff) >> 7) - CRTC.crtR11TxYCurr & 1020;
  1621:        CRTC.crtRasterStamp[a    ] = 0;
  1622:        CRTC.crtRasterStamp[a + 1] = 0;
  1623:        CRTC.crtRasterStamp[a + 2] = 0;
  1624:        CRTC.crtRasterStamp[a + 3] = 0;
  1625:      }  //mmdWb
  1626:     @Override protected void mmdWw (int a, int d) throws M68kException {
  1627:        XEiJ.mpuClockTime += XEiJ.busWaitTime.tvram;
  1628:        a &= XEiJ.BUS_MOTHER_MASK;
  1629:        int e;  //上位バイトのデータ
  1630:        int x;  //下位バイトのマスク
  1631:        int y;  //上位バイトのマスク
  1632:        if (CRTC.crtSimAccess) {  //同時アクセスあり
  1633:          a &= 0x00e1ffff;
  1634:          if (CRTC.crtBitMask) {  //同時アクセスあり,ビットマスクあり
  1635:            e = d >> 8 & ~(y = (x = CRTC.crtR23Mask) >> 8);
  1636:            d &= ~x;
  1637:            if (CRTC.crtSimPlane0) {
  1638:              MainMemory.mmrM8[a             ] = (byte) (MainMemory.mmrM8[a             ] & y | e);
  1639:              MainMemory.mmrM8[a + 0x00000001] = (byte) (MainMemory.mmrM8[a + 0x00000001] & x | d);
  1640:            }
  1641:            if (CRTC.crtSimPlane1) {
  1642:              MainMemory.mmrM8[a + 0x00020000] = (byte) (MainMemory.mmrM8[a + 0x00020000] & y | e);
  1643:              MainMemory.mmrM8[a + 0x00020001] = (byte) (MainMemory.mmrM8[a + 0x00020001] & x | d);
  1644:            }
  1645:            if (CRTC.crtSimPlane2) {
  1646:              MainMemory.mmrM8[a + 0x00040000] = (byte) (MainMemory.mmrM8[a + 0x00040000] & y | e);
  1647:              MainMemory.mmrM8[a + 0x00040001] = (byte) (MainMemory.mmrM8[a + 0x00040001] & x | d);
  1648:            }
  1649:            if (CRTC.crtSimPlane3) {
  1650:              MainMemory.mmrM8[a + 0x00060000] = (byte) (MainMemory.mmrM8[a + 0x00060000] & y | e);
  1651:              MainMemory.mmrM8[a + 0x00060001] = (byte) (MainMemory.mmrM8[a + 0x00060001] & x | d);
  1652:            }
  1653:          } else {  //同時アクセスあり,ビットマスクなし
  1654:            e = d >> 8;
  1655:            if (CRTC.crtSimPlane0) {
  1656:              MainMemory.mmrM8[a             ] = (byte) e;
  1657:              MainMemory.mmrM8[a + 0x00000001] = (byte) d;
  1658:            }
  1659:            if (CRTC.crtSimPlane1) {
  1660:              MainMemory.mmrM8[a + 0x00020000] = (byte) e;
  1661:              MainMemory.mmrM8[a + 0x00020001] = (byte) d;
  1662:            }
  1663:            if (CRTC.crtSimPlane2) {
  1664:              MainMemory.mmrM8[a + 0x00040000] = (byte) e;
  1665:              MainMemory.mmrM8[a + 0x00040001] = (byte) d;
  1666:            }
  1667:            if (CRTC.crtSimPlane3) {
  1668:              MainMemory.mmrM8[a + 0x00060000] = (byte) e;
  1669:              MainMemory.mmrM8[a + 0x00060001] = (byte) d;
  1670:            }
  1671:          }
  1672:        } else if (CRTC.crtBitMask) {  //同時アクセスなし,ビットマスクあり
  1673:          y = (x = CRTC.crtR23Mask) >> 8;
  1674:          MainMemory.mmrM8[a    ] = (byte) (MainMemory.mmrM8[a    ] & y | (d >> 8) & ~y);
  1675:          MainMemory.mmrM8[a + 1] = (byte) (MainMemory.mmrM8[a + 1] & x |  d       & ~x);
  1676:        } else {  //同時アクセスなし,ビットマスクなし
  1677:          if (MainMemory.MMR_USE_BYTE_BUFFER) {
  1678:            MainMemory.mmrBuffer.putShort (a, (short) d);
  1679:          } else {
  1680:            MainMemory.mmrM8[a    ] = (byte) (d >> 8);
  1681:            MainMemory.mmrM8[a + 1] = (byte)  d;
  1682:          }
  1683:        }
  1684:        //同時アクセスやビットマスクで1ピクセルも書き換えなくても更新することになる
  1685:        a = ((a & 0x0001ffff) >> 7) - CRTC.crtR11TxYCurr & 1020;
  1686:        CRTC.crtRasterStamp[a    ] = 0;
  1687:        CRTC.crtRasterStamp[a + 1] = 0;
  1688:        CRTC.crtRasterStamp[a + 2] = 0;
  1689:        CRTC.crtRasterStamp[a + 3] = 0;
  1690:      }  //mmdWw
  1691:     @Override protected void mmdWl (int a, int d) throws M68kException {
  1692:        XEiJ.mpuClockTime += XEiJ.busWaitTime.tvram * 2;
  1693:        a &= XEiJ.BUS_MOTHER_MASK;
  1694:        int e;  //下位ワードの上位バイトのデータ
  1695:        int f;  //上位ワードの下位バイトのデータ
  1696:        int g;  //上位ワードの上位バイトのデータ
  1697:        int x;  //下位バイトのマスク
  1698:        int y;  //上位バイトのマスク
  1699:        if (CRTC.crtSimAccess) {  //同時アクセスあり
  1700:          a &= 0x00e1ffff;
  1701:          if (CRTC.crtBitMask) {  //同時アクセスあり,ビットマスクあり
  1702:            g = d >> 24 & ~(y = (x = CRTC.crtR23Mask) >> 8);
  1703:            f = d >> 16 & ~x;
  1704:            e = d >>  8 & ~y;
  1705:            d &= ~x;
  1706:            if (CRTC.crtSimPlane0) {
  1707:              MainMemory.mmrM8[a             ] = (byte) (MainMemory.mmrM8[a             ] & y | g);
  1708:              MainMemory.mmrM8[a + 0x00000001] = (byte) (MainMemory.mmrM8[a + 0x00000001] & x | f);
  1709:              MainMemory.mmrM8[a + 0x00000002] = (byte) (MainMemory.mmrM8[a + 0x00000002] & y | e);
  1710:              MainMemory.mmrM8[a + 0x00000003] = (byte) (MainMemory.mmrM8[a + 0x00000003] & x | d);
  1711:            }
  1712:            if (CRTC.crtSimPlane1) {
  1713:              MainMemory.mmrM8[a + 0x00020000] = (byte) (MainMemory.mmrM8[a + 0x00020000] & y | g);
  1714:              MainMemory.mmrM8[a + 0x00020001] = (byte) (MainMemory.mmrM8[a + 0x00020001] & x | f);
  1715:              MainMemory.mmrM8[a + 0x00020002] = (byte) (MainMemory.mmrM8[a + 0x00020002] & y | e);
  1716:              MainMemory.mmrM8[a + 0x00020003] = (byte) (MainMemory.mmrM8[a + 0x00020003] & x | d);
  1717:            }
  1718:            if (CRTC.crtSimPlane2) {
  1719:              MainMemory.mmrM8[a + 0x00040000] = (byte) (MainMemory.mmrM8[a + 0x00040000] & y | g);
  1720:              MainMemory.mmrM8[a + 0x00040001] = (byte) (MainMemory.mmrM8[a + 0x00040001] & x | f);
  1721:              MainMemory.mmrM8[a + 0x00040002] = (byte) (MainMemory.mmrM8[a + 0x00040002] & y | e);
  1722:              MainMemory.mmrM8[a + 0x00040003] = (byte) (MainMemory.mmrM8[a + 0x00040003] & x | d);
  1723:            }
  1724:            if (CRTC.crtSimPlane3) {
  1725:              MainMemory.mmrM8[a + 0x00060000] = (byte) (MainMemory.mmrM8[a + 0x00060000] & y | g);
  1726:              MainMemory.mmrM8[a + 0x00060001] = (byte) (MainMemory.mmrM8[a + 0x00060001] & x | f);
  1727:              MainMemory.mmrM8[a + 0x00060002] = (byte) (MainMemory.mmrM8[a + 0x00060002] & y | e);
  1728:              MainMemory.mmrM8[a + 0x00060003] = (byte) (MainMemory.mmrM8[a + 0x00060003] & x | d);
  1729:            }
  1730:          } else {  //同時アクセスあり,ビットマスクなし
  1731:            g = d >> 24;
  1732:            f = d >> 16;
  1733:            e = d >>  8;
  1734:            if (CRTC.crtSimPlane0) {
  1735:              MainMemory.mmrM8[a             ] = (byte) g;
  1736:              MainMemory.mmrM8[a + 0x00000001] = (byte) f;
  1737:              MainMemory.mmrM8[a + 0x00000002] = (byte) e;
  1738:              MainMemory.mmrM8[a + 0x00000003] = (byte) d;
  1739:            }
  1740:            if (CRTC.crtSimPlane1) {
  1741:              MainMemory.mmrM8[a + 0x00020000] = (byte) g;
  1742:              MainMemory.mmrM8[a + 0x00020001] = (byte) f;
  1743:              MainMemory.mmrM8[a + 0x00020002] = (byte) e;
  1744:              MainMemory.mmrM8[a + 0x00020003] = (byte) d;
  1745:            }
  1746:            if (CRTC.crtSimPlane2) {
  1747:              MainMemory.mmrM8[a + 0x00040000] = (byte) g;
  1748:              MainMemory.mmrM8[a + 0x00040001] = (byte) f;
  1749:              MainMemory.mmrM8[a + 0x00040002] = (byte) e;
  1750:              MainMemory.mmrM8[a + 0x00040003] = (byte) d;
  1751:            }
  1752:            if (CRTC.crtSimPlane3) {
  1753:              MainMemory.mmrM8[a + 0x00060000] = (byte) g;
  1754:              MainMemory.mmrM8[a + 0x00060001] = (byte) f;
  1755:              MainMemory.mmrM8[a + 0x00060002] = (byte) e;
  1756:              MainMemory.mmrM8[a + 0x00060003] = (byte) d;
  1757:            }
  1758:          }
  1759:        } else if (CRTC.crtBitMask) {  //同時アクセスなし,ビットマスクあり
  1760:          y = (x = CRTC.crtR23Mask) >> 8;
  1761:          MainMemory.mmrM8[a    ] = (byte) (MainMemory.mmrM8[a    ] & y | (d >> 24) & ~y);
  1762:          MainMemory.mmrM8[a + 1] = (byte) (MainMemory.mmrM8[a + 1] & x | (d >> 16) & ~x);
  1763:          MainMemory.mmrM8[a + 2] = (byte) (MainMemory.mmrM8[a + 1] & y | (d >>  8) & ~y);
  1764:          MainMemory.mmrM8[a + 3] = (byte) (MainMemory.mmrM8[a + 1] & x |  d        & ~x);
  1765:        } else {  //同時アクセスなし,ビットマスクなし
  1766:          if (MainMemory.MMR_USE_BYTE_BUFFER) {
  1767:            MainMemory.mmrBuffer.putInt (a, d);
  1768:          } else {
  1769:            MainMemory.mmrM8[a    ] = (byte) (d >> 24);
  1770:            MainMemory.mmrM8[a + 1] = (byte) (d >> 16);
  1771:            MainMemory.mmrM8[a + 2] = (byte) (d >>  8);
  1772:            MainMemory.mmrM8[a + 3] = (byte)  d;
  1773:          }
  1774:        }
  1775:        //同時アクセスやビットマスクで1ピクセルも書き換えなくても更新することになる
  1776:        int b = ((a     & 0x0001ffff) >> 7) - CRTC.crtR11TxYCurr & 1020;
  1777:        CRTC.crtRasterStamp[b    ] = 0;
  1778:        CRTC.crtRasterStamp[b + 1] = 0;
  1779:        CRTC.crtRasterStamp[b + 2] = 0;
  1780:        CRTC.crtRasterStamp[b + 3] = 0;
  1781:        a = ((a + 2 & 0x0001ffff) >> 7) - CRTC.crtR11TxYCurr & 1020;
  1782:        if (a != b) {
  1783:          CRTC.crtRasterStamp[a    ] = 0;
  1784:          CRTC.crtRasterStamp[a + 1] = 0;
  1785:          CRTC.crtRasterStamp[a + 2] = 0;
  1786:          CRTC.crtRasterStamp[a + 3] = 0;
  1787:        }
  1788:      }  //mmdWl
  1789:   },  //MMD_TXT
  1790: 
  1791:   //--------------------------------------------------------------------------------
  1792:   //MMD_CRT CRTコントローラ
  1793:   //
  1794:   //  $00E80000~$00E8002F  ワードレジスタ
  1795:   //  $00E80030~$00E8003F  $0000
  1796:   //  $00E80040~$00E803FF  $00E80000~$00E8003Fの繰り返し
  1797:   //  $00E80400~$00E8047F  バスエラー
  1798:   //  $00E80480~$00E80481  ワードレジスタ
  1799:   //  $00E80482~$00E804FF  $00E80480~$00E80481の繰り返し
  1800:   //  $00E80500~$00E807FF  $00E80400~$00E804FFの繰り返し
  1801:   //  $00E80800~$00E81FFF  $00E80000~$00E807FFの繰り返し
  1802:   //
  1803:   MMD_CRT {
  1804:     @Override public String toString () {
  1805:       return Multilingual.mlnJapanese ? "CRT コントローラ" : "CRT Controller";
  1806:     }
  1807:     //リード
  1808:     @Override protected int mmdRbz (int a) throws M68kException {
  1809:        XEiJ.mpuClockTime += XEiJ.busWaitTime.crtc;
  1810:        int aa = a & 0x07ff;  //$00E80800~$00E81FFF→$00E80000~$00E807FF
  1811:        if (aa < 0x0400) {  //$00E80000~$00E803FF
  1812:          aa &= 0x003f;
  1813:          switch (aa) {
  1814:            //case 0x0001:  //R00の下位
  1815:            //  return CRTC.crtR00HFrontEndPort;
  1816:            //case 0x0003:  //R01の下位
  1817:            //  return CRTC.crtR01HSyncEndPort;
  1818:            //case 0x0005:  //R02の下位
  1819:            //  return CRTC.crtR02HBackEndPort;
  1820:            //case 0x0007:  //R03の下位
  1821:            //  return CRTC.crtR03HDispEndPort;
  1822:            //case 0x0008:  //R04の上位
  1823:            //  return CRTC.crtR04VFrontEndPort >> 8;
  1824:            //case 0x0009:  //R04の下位
  1825:            //  return CRTC.crtR04VFrontEndPort & 0xff;
  1826:            //case 0x000a:  //R05の上位
  1827:            //  return CRTC.crtR05VSyncEndPort >> 8;
  1828:            //case 0x000b:  //R05の下位
  1829:            //  return CRTC.crtR05VSyncEndPort & 0xff;
  1830:            //case 0x000c:  //R06の上位
  1831:            //  return CRTC.crtR06VBackEndPort >> 8;
  1832:            //case 0x000d:  //R06の下位
  1833:            //  return CRTC.crtR06VBackEndPort & 0xff;
  1834:            //case 0x000e:  //R07の上位
  1835:            //  return CRTC.crtR07VDispEndPort >> 8;
  1836:            //case 0x000f:  //R07の下位
  1837:            //  return CRTC.crtR07VDispEndPort & 0xff;
  1838:            //case 0x0011:  //R08の下位
  1839:            //  return CRTC.crtR08Adjust;
  1840:            //case 0x0012:  //R09の上位
  1841:            //  return CRTC.crtR09IRQRasterPort >> 8;
  1842:            //case 0x0013:  //R09の下位
  1843:            //  return CRTC.crtR09IRQRasterPort & 0xff;
  1844:            //case 0x0014:  //R10の上位
  1845:            //  return CRTC.crtR10TxXPort >> 8;
  1846:            //case 0x0015:  //R10の下位
  1847:            //  return CRTC.crtR10TxXPort & 0xff;
  1848:            //case 0x0016:  //R11の上位
  1849:            //  return CRTC.crtR11TxYCurr >> 8;
  1850:            //case 0x0017:  //R11の下位
  1851:            //  return CRTC.crtR11TxYCurr & 0xff;
  1852:            //case 0x0018:  //R12の上位
  1853:            //case 0x001c:  //R14の上位
  1854:            //case 0x0020:  //R16の上位
  1855:            //case 0x0024:  //R18の上位
  1856:            //  return CRTC.crtR12GrXPort[(aa - 0x0018) >> 2] >> 8;
  1857:            //case 0x0019:  //R12の下位
  1858:            //case 0x001d:  //R14の下位
  1859:            //case 0x0021:  //R16の下位
  1860:            //case 0x0025:  //R18の下位
  1861:            //  return CRTC.crtR12GrXPort[(aa - 0x0018) >> 2] & 0xff;
  1862:            //case 0x001a:  //R13の上位
  1863:            //case 0x001e:  //R15の上位
  1864:            //case 0x0022:  //R17の上位
  1865:            //case 0x0026:  //R19の上位
  1866:            //  return CRTC.crtR13GrYPort[(aa - 0x0018) >> 2] >> 8;
  1867:            //case 0x001b:  //R13の下位
  1868:            //case 0x001f:  //R15の下位
  1869:            //case 0x0023:  //R17の下位
  1870:            //case 0x0027:  //R19の下位
  1871:            //  return CRTC.crtR13GrYPort[(aa - 0x0018) >> 2] & 0xff;
  1872:          case 0x0028:  //R20の上位
  1873:            return (CRTC.crtTextStorage    << 4 |
  1874:                    CRTC.crtGraphicStorage << 3 |
  1875:                    CRTC.crtMemoryModePort);
  1876:          case 0x0029:  //R20の下位
  1877:            return (CRTC.crtHighResoPort << 4 |
  1878:                    CRTC.crtVResoPort    << 2 |
  1879:                    CRTC.crtHResoPort);
  1880:          case 0x002a:  //R21の上位
  1881:            return ((CRTC.crtBitMask   ? 0b00000010 : 0) |
  1882:                    (CRTC.crtSimAccess ? 0b00000001 : 0));
  1883:          case 0x002b:  //R21の下位
  1884:            return ((CRTC.crtSimPlane3 ? 0b10000000 : 0) |
  1885:                    (CRTC.crtSimPlane2 ? 0b01000000 : 0) |
  1886:                    (CRTC.crtSimPlane1 ? 0b00100000 : 0) |
  1887:                    (CRTC.crtSimPlane0 ? 0b00010000 : 0) |
  1888:                    (CRTC.crtCCPlane3  ? 0b00001000 : 0) |
  1889:                    (CRTC.crtCCPlane2  ? 0b00000100 : 0) |
  1890:                    (CRTC.crtCCPlane1  ? 0b00000010 : 0) |
  1891:                    (CRTC.crtCCPlane0  ? 0b00000001 : 0));
  1892:            //case 0x002c:  //R22の上位
  1893:            //  return CRTC.crtR22SrcBlock;
  1894:            //case 0x002d:  //R22の下位
  1895:            //  return CRTC.crtR22DstBlock;
  1896:            //case 0x002e:  //R23の上位
  1897:            //  return CRTC.crtR23Mask >> 8;
  1898:            //case 0x002f:  //R23の下位
  1899:            //  return CRTC.crtR23Mask & 0xff;
  1900:            //case 0x0000:  //R00の上位
  1901:            //case 0x0002:  //R01の上位
  1902:            //case 0x0004:  //R02の上位
  1903:            //case 0x0006:  //R03の上位
  1904:            //case 0x0010:  //R08の上位
  1905:            //case 0x0030:  //R24の上位
  1906:            //case 0x0031:  //R24の下位
  1907:            //case 0x0032:  //R25の上位
  1908:            //case 0x0033:  //R25の下位
  1909:            //case 0x0034:  //R26の上位
  1910:            //case 0x0035:  //R26の下位
  1911:            //case 0x0036:  //R27の上位
  1912:            //case 0x0037:  //R27の下位
  1913:            //case 0x0038:  //R28の上位
  1914:            //case 0x0039:  //R28の下位
  1915:            //case 0x003a:  //R29の上位
  1916:            //case 0x003b:  //R29の下位
  1917:            //case 0x003c:  //R30の上位
  1918:            //case 0x003d:  //R30の下位
  1919:            //case 0x003e:  //R31の上位
  1920:            //case 0x003f:  //R31の下位
  1921:          default:
  1922:            return 0x00;
  1923:            //return VideoController.vcnMode.ordinal () >> 8;
  1924:            //return VideoController.vcnMode.ordinal () & 0xff;
  1925:          }
  1926:        } else {  //$00E80400~$00E807FF
  1927:          aa &= 0xff;  //$00E80500~$00E807FF→$00E80400~$00E804FF
  1928:          if (aa < 0x80) {  //$00E80400~$00E8047F
  1929:            return super.mmdRbz (a);  //バスエラー
  1930:          } else {  //$00E80480~$00E804FF
  1931:            aa &= 0x01;  //$00E80482~$00E804FF→$00E80480~$00E80481
  1932:            if (aa == 0) {  //動作ポートの上位
  1933:              return 0;
  1934:            } else {  //動作ポートの下位
  1935:              return ((CRTC.crtRasterCopyOn ? 8 : 0) |  //ラスタコピー
  1936:                      (CRTC.crtClearStandby || CRTC.crtClearFrames != 0 ? 2 : 0));  //高速クリア
  1937:            }
  1938:          }
  1939:        }
  1940:      }  //mmdRbz
  1941:     @Override protected int mmdRwz (int a) throws M68kException {
  1942:        XEiJ.mpuClockTime += XEiJ.busWaitTime.crtc;
  1943:        int aa = a & 0x07ff;  //$00E80800~$00E81FFF→$00E80000~$00E807FF
  1944:        if (aa < 0x0400) {  //$00E80000~$00E803FF
  1945:          aa &= 0x003f;
  1946:          switch (aa) {
  1947:            //case 0x0000:  //R00
  1948:            //  return CRTC.crtR00HFrontEndPort;
  1949:            //case 0x0002:  //R01
  1950:            //  return CRTC.crtR01HSyncEndPort;
  1951:            //case 0x0004:  //R02
  1952:            //  return CRTC.crtR02HBackEndPort;
  1953:            //case 0x0006:  //R03
  1954:            //  return CRTC.crtR03HDispEndPort;
  1955:            //case 0x0008:  //R04
  1956:            //  return CRTC.crtR04VFrontEndPort;
  1957:            //case 0x000a:  //R05
  1958:            //  return CRTC.crtR05VSyncEndPort;
  1959:            //case 0x000c:  //R06
  1960:            //  return CRTC.crtR06VBackEndPort;
  1961:            //case 0x000e:  //R07
  1962:            //  return CRTC.crtR07VDispEndPort;
  1963:            //case 0x0010:  //R08
  1964:            //  return CRTC.crtR08Adjust;
  1965:            //case 0x0012:  //R09
  1966:            //  return CRTC.crtR09IRQRasterPort;
  1967:            //case 0x0014:  //R10
  1968:            //  return CRTC.crtR10TxXPort;
  1969:            //case 0x0016:  //R11
  1970:            //  return CRTC.crtR11TxYPort;
  1971:            //case 0x0018:  //R12
  1972:            //case 0x001c:  //R14
  1973:            //case 0x0020:  //R16
  1974:            //case 0x0024:  //R18
  1975:            //  return CRTC.crtR12GrXPort[(aa - 0x0018) >> 2];
  1976:            //case 0x001a:  //R13
  1977:            //case 0x001e:  //R15
  1978:            //case 0x0022:  //R17
  1979:            //case 0x0026:  //R19
  1980:            //  return CRTC.crtR13GrYPort[(aa - 0x0018) >> 2];
  1981:          case 0x0028:  //R20
  1982:            return (CRTC.crtTextStorage    << 12 |
  1983:                    CRTC.crtGraphicStorage << 11 |
  1984:                    CRTC.crtMemoryModePort <<  8 |
  1985:                    CRTC.crtHighResoPort   <<  4 |
  1986:                    CRTC.crtVResoPort      <<  2 |
  1987:                    CRTC.crtHResoPort);
  1988:          case 0x002a:  //R21
  1989:            return ((CRTC.crtBitMask   ? 0b00000010_00000000 : 0) |
  1990:                    (CRTC.crtSimAccess ? 0b00000001_00000000 : 0) |
  1991:                    (CRTC.crtSimPlane3 ? 0b00000000_10000000 : 0) |
  1992:                    (CRTC.crtSimPlane2 ? 0b00000000_01000000 : 0) |
  1993:                    (CRTC.crtSimPlane1 ? 0b00000000_00100000 : 0) |
  1994:                    (CRTC.crtSimPlane0 ? 0b00000000_00010000 : 0) |
  1995:                    (CRTC.crtCCPlane3  ? 0b00000000_00001000 : 0) |
  1996:                    (CRTC.crtCCPlane2  ? 0b00000000_00000100 : 0) |
  1997:                    (CRTC.crtCCPlane1  ? 0b00000000_00000010 : 0) |
  1998:                    (CRTC.crtCCPlane0  ? 0b00000000_00000001 : 0));
  1999:            //case 0x002c:  //R22
  2000:            //  return CRTC.crtR22SrcBlock << 8 | CRTC.crtR22DstBlock;
  2001:            //case 0x002e:  //R23
  2002:            //  return CRTC.crtR23Mask;
  2003:            //case 0x0030:  //R24
  2004:            //case 0x0032:  //R25
  2005:            //case 0x0034:  //R26
  2006:            //case 0x0036:  //R27
  2007:            //case 0x0038:  //R28
  2008:            //case 0x003a:  //R29
  2009:            //case 0x003c:  //R30
  2010:            //case 0x003e:  //R31
  2011:          default:
  2012:            return 0x0000;
  2013:          }
  2014:        } else {  //$00E80400~$00E807FF
  2015:          aa &= 0xff;  //$00E80500~$00E807FF→$00E80400~$00E804FF
  2016:          if (aa < 0x80) {  //$00E80400~$00E8047F
  2017:            return super.mmdRbz (a);  //バスエラー
  2018:          } else {  //$00E80480~$00E804FF  動作ポート
  2019:            return ((CRTC.crtRasterCopyOn ? 8 : 0) |  //ラスタコピー
  2020:                    (CRTC.crtClearStandby || CRTC.crtClearFrames != 0 ? 2 : 0));  //高速クリア
  2021:          }
  2022:        }
  2023:      }  //mmdRwz
  2024:     @Override protected int mmdRls (int a) throws M68kException {
  2025:        return mmdRwz (a) << 16 | mmdRwz (a + 2);
  2026:      }
  2027:     //ライト
  2028:     @Override protected void mmdWb (int a, int d) throws M68kException {
  2029:        XEiJ.mpuClockTime += XEiJ.busWaitTime.crtc;
  2030:        int aa = a & 0x07ff;  //$00E80800~$00E81FFF→$00E80000~$00E807FF
  2031:        if (aa < 0x0400) {  //$00E80000~$00E803FF
  2032:          aa &= 0x003f;
  2033:          switch (aa) {
  2034:          case 0x0001:  //R00の下位
  2035:            CRTC.crtR00HFrontEndPort = (d & 0xff) | (CRTC.crtR00Bit0Zero ? 0x00 : 0x01);
  2036:            {
  2037:              int curr = CRTC.crtR00HFrontEndMask == 0 ? CRTC.crtR00HFrontEndPort : CRTC.crtR00HFrontEndTest;
  2038:              if (CRTC.crtR00HFrontEndCurr != curr) {
  2039:                CRTC.crtR00HFrontEndCurr = curr;
  2040:                CRTC.crtRestart ();
  2041:              }
  2042:            }
  2043:          return;
  2044:          case 0x0003:  //R01の下位
  2045:            CRTC.crtR01HSyncEndPort = d & 0xff;
  2046:            {
  2047:              int curr = CRTC.crtR01HSyncEndMask == 0 ? CRTC.crtR01HSyncEndPort : CRTC.crtR01HSyncEndTest;
  2048:              if (CRTC.crtR01HSyncEndCurr != curr) {
  2049:                CRTC.crtR01HSyncEndCurr = curr;
  2050:                CRTC.crtRestart ();
  2051:              }
  2052:            }
  2053:            return;
  2054:          case 0x0005:  //R02の下位
  2055:            CRTC.crtR02HBackEndPort = d & 0xff;
  2056:            {
  2057:              int curr = CRTC.crtR02HBackEndMask == 0 ? CRTC.crtR02HBackEndPort : CRTC.crtR02HBackEndTest;
  2058:              if (CRTC.crtR02HBackEndCurr != curr) {
  2059:                CRTC.crtR02HBackEndCurr = curr;
  2060:                CRTC.crtRestart ();
  2061:              }
  2062:            }
  2063:            return;
  2064:          case 0x0007:  //R03の下位
  2065:            CRTC.crtR03HDispEndPort = d & 0xff;
  2066:            {
  2067:              int curr = CRTC.crtR03HDispEndMask == 0 ? CRTC.crtR03HDispEndPort : CRTC.crtR03HDispEndTest;
  2068:              if (CRTC.crtR03HDispEndCurr != curr) {
  2069:                CRTC.crtR03HDispEndCurr = curr;
  2070:                CRTC.crtRestart ();
  2071:              }
  2072:            }
  2073:            return;
  2074:          case 0x0008:  //R04の上位
  2075:            CRTC.crtR04VFrontEndPort = (d & (CRTC.crtVerticalMask >> 8)) << 8 | (CRTC.crtR04VFrontEndPort & 0xff);
  2076:            {
  2077:              int curr = CRTC.crtR04VFrontEndMask == 0 ? CRTC.crtR04VFrontEndPort : CRTC.crtR04VFrontEndTest;
  2078:              if (CRTC.crtR04VFrontEndCurr != curr) {
  2079:                CRTC.crtR04VFrontEndCurr = curr;
  2080:                if (CRTC.CRT_RASTER_HASH_ON) {
  2081:                  CRTC.crtUpdateRasterHash ();
  2082:                }
  2083:                CRTC.crtRestart ();
  2084:              }
  2085:            }
  2086:            return;
  2087:          case 0x0009:  //R04の下位
  2088:            CRTC.crtR04VFrontEndPort = (CRTC.crtR04VFrontEndPort & ~0xff) | (d & 0xff);
  2089:            {
  2090:              int curr = CRTC.crtR04VFrontEndMask == 0 ? CRTC.crtR04VFrontEndPort : CRTC.crtR04VFrontEndTest;
  2091:              if (CRTC.crtR04VFrontEndCurr != curr) {
  2092:                CRTC.crtR04VFrontEndCurr = curr;
  2093:                if (CRTC.CRT_RASTER_HASH_ON) {
  2094:                  CRTC.crtUpdateRasterHash ();
  2095:                }
  2096:                CRTC.crtRestart ();
  2097:              }
  2098:            }
  2099:            return;
  2100:          case 0x000a:  //R05の上位
  2101:            CRTC.crtR05VSyncEndPort = (d & (CRTC.crtVerticalMask >> 8)) << 8 | (CRTC.crtR05VSyncEndPort & 0xff);
  2102:            {
  2103:              int curr = CRTC.crtR05VSyncEndMask == 0 ? CRTC.crtR05VSyncEndPort : CRTC.crtR05VSyncEndTest;
  2104:              if (CRTC.crtR05VSyncEndCurr != curr) {
  2105:                CRTC.crtR05VSyncEndCurr = curr;
  2106:                CRTC.crtRestart ();
  2107:              }
  2108:            }
  2109:            return;
  2110:          case 0x000b:  //R05の下位
  2111:            CRTC.crtR05VSyncEndPort = (CRTC.crtR05VSyncEndPort & ~0xff) | (d & 0xff);
  2112:            {
  2113:              int curr = CRTC.crtR05VSyncEndMask == 0 ? CRTC.crtR05VSyncEndPort : CRTC.crtR05VSyncEndTest;
  2114:              if (CRTC.crtR05VSyncEndCurr != curr) {
  2115:                CRTC.crtR05VSyncEndCurr = curr;
  2116:                CRTC.crtRestart ();
  2117:              }
  2118:            }
  2119:            return;
  2120:          case 0x000c:  //R06の上位
  2121:            CRTC.crtR06VBackEndPort = (d & (CRTC.crtVerticalMask >> 8)) << 8 | (CRTC.crtR06VBackEndPort & 0xff);
  2122:            {
  2123:              int curr = CRTC.crtR06VBackEndMask == 0 ? CRTC.crtR06VBackEndPort : CRTC.crtR06VBackEndTest;
  2124:              if (CRTC.crtR06VBackEndCurr != curr) {
  2125:                CRTC.crtR06VBackEndCurr = curr;
  2126:                CRTC.crtVDispStart = curr + 1;
  2127:                if (CRTC.CRT_RASTER_HASH_ON) {
  2128:                  CRTC.crtUpdateRasterHash ();
  2129:                }
  2130:                CRTC.crtRestart ();
  2131:              }
  2132:            }
  2133:            return;
  2134:          case 0x000d:  //R06の下位
  2135:            CRTC.crtR06VBackEndPort = (CRTC.crtR06VBackEndPort & ~0xff) | (d & 0xff);
  2136:            {
  2137:              int curr = CRTC.crtR06VBackEndMask == 0 ? CRTC.crtR06VBackEndPort : CRTC.crtR06VBackEndTest;
  2138:              if (CRTC.crtR06VBackEndCurr != curr) {
  2139:                CRTC.crtR06VBackEndCurr = curr;
  2140:                CRTC.crtVDispStart = curr + 1;
  2141:                if (CRTC.CRT_RASTER_HASH_ON) {
  2142:                  CRTC.crtUpdateRasterHash ();
  2143:                }
  2144:                CRTC.crtRestart ();
  2145:              }
  2146:            }
  2147:            return;
  2148:          case 0x000e:  //R07の上位
  2149:            CRTC.crtR07VDispEndPort = (d & (CRTC.crtVerticalMask >> 8)) << 8 | (CRTC.crtR07VDispEndPort & 0xff);
  2150:            {
  2151:              int curr = CRTC.crtR07VDispEndMask == 0 ? CRTC.crtR07VDispEndPort : CRTC.crtR07VDispEndTest;
  2152:              if (CRTC.crtR07VDispEndCurr != curr) {
  2153:                CRTC.crtR07VDispEndCurr = curr;
  2154:                CRTC.crtVIdleStart = curr + 1;
  2155:                if (CRTC.CRT_RASTER_HASH_ON) {
  2156:                  CRTC.crtUpdateRasterHash ();
  2157:                }
  2158:                CRTC.crtRestart ();
  2159:              }
  2160:            }
  2161:            return;
  2162:          case 0x000f:  //R07の下位
  2163:            CRTC.crtR07VDispEndPort = (CRTC.crtR07VDispEndPort & ~0xff) | (d & 0xff);
  2164:            {
  2165:              int curr = CRTC.crtR07VDispEndMask == 0 ? CRTC.crtR07VDispEndPort : CRTC.crtR07VDispEndTest;
  2166:              if (CRTC.crtR07VDispEndCurr != curr) {
  2167:                CRTC.crtR07VDispEndCurr = curr;
  2168:                CRTC.crtVIdleStart = curr + 1;
  2169:                if (CRTC.CRT_RASTER_HASH_ON) {
  2170:                  CRTC.crtUpdateRasterHash ();
  2171:                }
  2172:                CRTC.crtRestart ();
  2173:              }
  2174:            }
  2175:            return;
  2176:          case 0x0011:  //R08の下位
  2177:            d &= 0xff;
  2178:            if (CRTC.crtR08Adjust != d) {
  2179:              CRTC.crtR08Adjust = d;
  2180:              CRTC.crtRestart ();
  2181:            }
  2182:            return;
  2183:          case 0x0012:  //R09の上位
  2184:            CRTC.crtR09IRQRasterPort = (d & (CRTC.crtVerticalMask >> 8)) << 8 | (CRTC.crtR09IRQRasterPort & 0xff);
  2185:            {
  2186:              int curr = CRTC.crtR09IRQRasterMask == 0 ? CRTC.crtR09IRQRasterPort : CRTC.crtR09IRQRasterTest;
  2187:              if (CRTC.crtR09IRQRasterCurr != curr) {
  2188:                CRTC.crtR09IRQRasterCurr = curr;
  2189:                if (CRTC.CRT_RASTER_HASH_ON) {
  2190:                  CRTC.crtUpdateRasterHash ();
  2191:                }
  2192:                if (RasterBreakPoint.RBP_ON) {
  2193:                  RasterBreakPoint.rbpCheckIRQ ();
  2194:                }
  2195:              }
  2196:            }
  2197:            return;
  2198:          case 0x0013:  //R09の下位
  2199:            CRTC.crtR09IRQRasterPort = (CRTC.crtR09IRQRasterPort & ~0xff) | (d & 0xff);
  2200:            {
  2201:              int curr = CRTC.crtR09IRQRasterMask == 0 ? CRTC.crtR09IRQRasterPort : CRTC.crtR09IRQRasterTest;
  2202:              if (CRTC.crtR09IRQRasterCurr != curr) {
  2203:                CRTC.crtR09IRQRasterCurr = curr;
  2204:                if (CRTC.CRT_RASTER_HASH_ON) {
  2205:                  CRTC.crtUpdateRasterHash ();
  2206:                }
  2207:                if (RasterBreakPoint.RBP_ON) {
  2208:                  RasterBreakPoint.rbpCheckIRQ ();
  2209:                }
  2210:              }
  2211:            }
  2212:            return;
  2213:          case 0x0014:  //R10の上位
  2214:            CRTC.crtR10TxXPort = (d & 0x03) << 8 | (CRTC.crtR10TxXPort & 0xff);
  2215:            {
  2216:              int curr = CRTC.crtR10TxXMask == 0 ? CRTC.crtR10TxXPort : CRTC.crtR10TxXTest;
  2217:              if (CRTC.crtR10TxXCurr != curr) {
  2218:                CRTC.crtR10TxXCurr = curr;
  2219:                CRTC.crtAllStamp += 2;
  2220:              }
  2221:            }
  2222:            return;
  2223:          case 0x0015:  //R10の下位
  2224:            CRTC.crtR10TxXPort = (CRTC.crtR10TxXPort & ~0xff) | (d & 0xff);
  2225:            {
  2226:              int curr = CRTC.crtR10TxXMask == 0 ? CRTC.crtR10TxXPort : CRTC.crtR10TxXTest;
  2227:              if (CRTC.crtR10TxXCurr != curr) {
  2228:                CRTC.crtR10TxXCurr = curr;
  2229:                CRTC.crtAllStamp += 2;
  2230:              }
  2231:            }
  2232:            return;
  2233:          case 0x0016:  //R11の上位
  2234:            CRTC.crtR11TxYPort = (d & 0x03) << 8 | (CRTC.crtR11TxYPort & 0xff);
  2235:            {
  2236:              int curr = CRTC.crtR11TxYMask == 0 ? CRTC.crtR11TxYPort : CRTC.crtR11TxYTest;
  2237:              if (CRTC.crtR11TxYCurr != curr) {
  2238:                CRTC.crtR11TxYCurr = curr;
  2239:                //CRTC.crtAllStamp += 2;  //ラッチするとき更新する
  2240:              }
  2241:            }
  2242:            return;
  2243:          case 0x0017:  //R11の下位
  2244:            CRTC.crtR11TxYPort = (CRTC.crtR11TxYPort & ~0xff) | (d & 0xff);
  2245:            {
  2246:              int curr = CRTC.crtR11TxYMask == 0 ? CRTC.crtR11TxYPort : CRTC.crtR11TxYTest;
  2247:              if (CRTC.crtR11TxYCurr != curr) {
  2248:                CRTC.crtR11TxYCurr = curr;
  2249:                //CRTC.crtAllStamp += 2;  //ラッチするとき更新する
  2250:              }
  2251:            }
  2252:            return;
  2253:          case 0x0018:  //R12の上位
  2254:          case 0x001c:  //R14の上位
  2255:          case 0x0020:  //R16の上位
  2256:          case 0x0024:  //R18の上位
  2257:            {
  2258:              int p = (aa - 0x0018) >> 2;  //0,1,2,3
  2259:              CRTC.crtR12GrXPort[p] = (d & (p == 0 ? 0x03 : 0x01)) << 8 | (CRTC.crtR12GrXPort[p] & 0xff);
  2260:              int curr = CRTC.crtR12GrXMask[p] == 0 ? CRTC.crtR12GrXPort[p] : CRTC.crtR12GrXTest[p];
  2261:              if (CRTC.crtR12GrXCurr[p] != curr) {
  2262:                CRTC.crtR12GrXCurr[p] = curr;
  2263:                CRTC.crtAllStamp += 2;
  2264:              }
  2265:            }
  2266:            return;
  2267:          case 0x0019:  //R12の下位
  2268:          case 0x001d:  //R14の下位
  2269:          case 0x0021:  //R16の下位
  2270:          case 0x0025:  //R18の下位
  2271:            {
  2272:              int p = (aa - 0x0018) >> 2;  //0,1,2,3
  2273:              CRTC.crtR12GrXPort[p] = (CRTC.crtR12GrXPort[p] & ~0xff) | (d & 0xff);
  2274:              int curr = CRTC.crtR12GrXMask[p] == 0 ? CRTC.crtR12GrXPort[p] : CRTC.crtR12GrXTest[p];
  2275:              if (CRTC.crtR12GrXCurr[p] != curr) {
  2276:                CRTC.crtR12GrXCurr[p] = curr;
  2277:                CRTC.crtAllStamp += 2;
  2278:              }
  2279:            }
  2280:            return;
  2281:          case 0x001a:  //R13の上位
  2282:          case 0x001e:  //R15の上位
  2283:          case 0x0022:  //R17の上位
  2284:          case 0x0026:  //R19の上位
  2285:            {
  2286:              int p = (aa - 0x0018) >> 2;  //0,1,2,3
  2287:              CRTC.crtR13GrYPort[p] = (d & (p == 0 ? 0x03 : 0x01)) << 8 | (CRTC.crtR13GrYPort[p] & 0xff);
  2288:              int curr = CRTC.crtR13GrYMask[p] == 0 ? CRTC.crtR13GrYPort[p] : CRTC.crtR13GrYTest[p];
  2289:              if (CRTC.crtR13GrYCurr[p] != curr) {
  2290:                CRTC.crtR13GrYCurr[p] = curr;
  2291:                //CRTC.crtAllStamp += 2;  //ラッチするとき更新する
  2292:              }
  2293:            }
  2294:            return;
  2295:          case 0x001b:  //R13の下位
  2296:          case 0x001f:  //R15の下位
  2297:          case 0x0023:  //R17の下位
  2298:          case 0x0027:  //R19の下位
  2299:            {
  2300:              int p = (aa - 0x0018) >> 2;  //0,1,2,3
  2301:              CRTC.crtR13GrYPort[p] = (CRTC.crtR13GrYPort[p] & ~0xff) | (d & 0xff);
  2302:              int curr = CRTC.crtR13GrYMask[p] == 0 ? CRTC.crtR13GrYPort[p] : CRTC.crtR13GrYTest[p];
  2303:              if (CRTC.crtR13GrYCurr[p] != curr) {
  2304:                CRTC.crtR13GrYCurr[p] = curr;
  2305:                //CRTC.crtAllStamp += 2;  //ラッチするとき更新する
  2306:              }
  2307:            }
  2308:            return;
  2309:          case 0x0028:  //R20の上位
  2310:            CRTC.crtSetMemoryMode (d >> 4, d >> 3, d);
  2311:            return;
  2312:          case 0x0029:  //R20の下位
  2313:            CRTC.crtHighResoPort = d >>> 4 & 1;
  2314:            CRTC.crtVResoPort    = d >>> 2 & 3;
  2315:            CRTC.crtHResoPort    = d       & 3;
  2316:            SpriteScreen.sprAccessible = (d & 0b10010) != 0b10010;
  2317:            int highResoCurr = CRTC.crtHighResoMask == 0 ? CRTC.crtHighResoPort : CRTC.crtHighResoTest;
  2318:            int vResoCurr = CRTC.crtVResoMask == 0 ? CRTC.crtVResoPort : CRTC.crtVResoTest;
  2319:            int hResoCurr = CRTC.crtHResoMask == 0 ? CRTC.crtHResoPort : CRTC.crtHResoTest;
  2320:            if (CRTC.crtHighResoCurr != highResoCurr ||
  2321:                CRTC.crtVResoCurr != vResoCurr ||
  2322:                CRTC.crtHResoCurr != hResoCurr) {
  2323:              CRTC.crtHighResoCurr = highResoCurr;
  2324:              CRTC.crtVResoCurr = vResoCurr;
  2325:              CRTC.crtHResoCurr = hResoCurr;
  2326:              CRTC.crtRestart ();
  2327:            }
  2328:            return;
  2329:          case 0x002a:  //R21の上位
  2330:            CRTC.crtBitMask   = XEiJ.TEST_BIT_1_SHIFT ? d << 31 - 1 < 0 : (d & 2) != 0;
  2331:            CRTC.crtSimAccess = XEiJ.TEST_BIT_0_SHIFT ? d << 31 - 0 < 0 : (d & 1) != 0;
  2332:            return;
  2333:          case 0x002b:  //R21の下位
  2334:            CRTC.crtSimPlane3 = (byte) d < 0;  //(d & 128) != 0。d << 24 < 0
  2335:            CRTC.crtSimPlane2 = d << 25 < 0;  //(d & 64) != 0
  2336:            CRTC.crtSimPlane1 = d << 26 < 0;  //(d & 32) != 0
  2337:            CRTC.crtSimPlane0 = d << 27 < 0;  //(d & 16) != 0
  2338:            CRTC.crtCCPlane3  = XEiJ.TEST_BIT_3_SHIFT ? d << 31 - 3 < 0 : (d & 8) != 0;
  2339:            CRTC.crtCCPlane2  = XEiJ.TEST_BIT_2_SHIFT ? d << 31 - 2 < 0 : (d & 4) != 0;
  2340:            CRTC.crtCCPlane1  = XEiJ.TEST_BIT_1_SHIFT ? d << 31 - 1 < 0 : (d & 2) != 0;
  2341:            CRTC.crtCCPlane0  = XEiJ.TEST_BIT_0_SHIFT ? d << 31 - 0 < 0 : (d & 1) != 0;
  2342:            return;
  2343:          case 0x002c:  //R22の上位
  2344:            CRTC.crtR22SrcBlock = d & 0xff;
  2345:            return;
  2346:          case 0x002d:  //R22の下位
  2347:            CRTC.crtR22DstBlock = d & 0xff;
  2348:            return;
  2349:          case 0x002e:  //R23の上位
  2350:            CRTC.crtR23Mask = (d & 0xff) << 8 | (CRTC.crtR23Mask & 0xff);
  2351:            return;
  2352:          case 0x002f:  //R23の下位
  2353:            CRTC.crtR23Mask = (CRTC.crtR23Mask & ~0xff) | (d & 0xff);
  2354:            return;
  2355:            //case 0x0000:  //R00の上位
  2356:            //case 0x0002:  //R01の上位
  2357:            //case 0x0004:  //R02の上位
  2358:            //case 0x0006:  //R03の上位
  2359:            //case 0x0010:  //R08の上位
  2360:            //case 0x0030:  //R24の上位
  2361:            //case 0x0031:  //R24の下位
  2362:            //case 0x0032:  //R25の上位
  2363:            //case 0x0033:  //R25の下位
  2364:            //case 0x0034:  //R26の上位
  2365:            //case 0x0035:  //R26の下位
  2366:            //case 0x0036:  //R27の上位
  2367:            //case 0x0037:  //R27の下位
  2368:            //case 0x0038:  //R28の上位
  2369:            //case 0x0039:  //R28の下位
  2370:            //case 0x003a:  //R29の上位
  2371:            //case 0x003b:  //R29の下位
  2372:            //case 0x003c:  //R30の上位
  2373:            //case 0x003d:  //R30の下位
  2374:            //case 0x003e:  //R31の上位
  2375:            //case 0x003f:  //R31の下位
  2376:          default:
  2377:            return;
  2378:          }
  2379:        } else {  //$00E80400~$00E807FF
  2380:          aa &= 0xff;  //$00E80500~$00E807FF→$00E80400~$00E804FF
  2381:          if (aa < 0x80) {  //$00E80400~$00E8047F
  2382:            super.mmdWb (a, d);  //バスエラー
  2383:          } else {  //$00E80480~$00E804FF
  2384:            aa &= 0x01;  //$00E80482~$00E804FF→$00E80480~$00E80481
  2385:            if (aa == 0) {  //動作ポートの上位
  2386:              return;
  2387:            } else {  //動作ポートの下位
  2388:              boolean rasterCopyOn = (d & 8) != 0;
  2389:              if (CRTC.crtRasterCopyOn != rasterCopyOn) {
  2390:                CRTC.crtRasterCopyOn = rasterCopyOn;  //ラスタコピー
  2391:                if (CRTC.CRT_RASTER_HASH_ON) {
  2392:                  CRTC.crtUpdateRasterHash ();
  2393:                }
  2394:              }
  2395:              CRTC.crtClearStandby = (d & 2) != 0;  //高速クリア
  2396:              return;
  2397:            }
  2398:          }
  2399:        }
  2400:      }
  2401:     @Override protected void mmdWw (int a, int d) throws M68kException {
  2402:        XEiJ.mpuClockTime += XEiJ.busWaitTime.crtc;
  2403:        int aa = a & 0x07ff;  //$00E80800~$00E81FFF→$00E80000~$00E807FF
  2404:        if (aa < 0x0400) {  //$00E80000~$00E803FF
  2405:          aa &= 0x003f;
  2406:          switch (aa) {
  2407:          case 0x0000:  //R00
  2408:            CRTC.crtR00HFrontEndPort = (d & 0xff) | (CRTC.crtR00Bit0Zero ? 0x00 : 0x01);
  2409:            {
  2410:              int curr = CRTC.crtR00HFrontEndMask == 0 ? CRTC.crtR00HFrontEndPort : CRTC.crtR00HFrontEndTest;
  2411:              if (CRTC.crtR00HFrontEndCurr != curr) {
  2412:                CRTC.crtR00HFrontEndCurr = curr;
  2413:                CRTC.crtRestart ();
  2414:              }
  2415:            }
  2416:            return;
  2417:          case 0x0002:  //R01
  2418:            CRTC.crtR01HSyncEndPort = d & 0xff;
  2419:            {
  2420:              int curr = CRTC.crtR01HSyncEndMask == 0 ? CRTC.crtR01HSyncEndPort : CRTC.crtR01HSyncEndTest;
  2421:              if (CRTC.crtR01HSyncEndCurr != curr) {
  2422:                CRTC.crtR01HSyncEndCurr = curr;
  2423:                CRTC.crtRestart ();
  2424:              }
  2425:            }
  2426:            return;
  2427:          case 0x0004:  //R02
  2428:            CRTC.crtR02HBackEndPort = d & 0xff;
  2429:            {
  2430:              int curr = CRTC.crtR02HBackEndMask == 0 ? CRTC.crtR02HBackEndPort : CRTC.crtR02HBackEndTest;
  2431:              if (CRTC.crtR02HBackEndCurr != curr) {
  2432:                CRTC.crtR02HBackEndCurr = curr;
  2433:                CRTC.crtRestart ();
  2434:              }
  2435:            }
  2436:            return;
  2437:          case 0x0006:  //R03
  2438:            CRTC.crtR03HDispEndPort = d & 0xff;
  2439:            {
  2440:              int curr = CRTC.crtR03HDispEndMask == 0 ? CRTC.crtR03HDispEndPort : CRTC.crtR03HDispEndTest;
  2441:              if (CRTC.crtR03HDispEndCurr != curr) {
  2442:                CRTC.crtR03HDispEndCurr = curr;
  2443:                CRTC.crtRestart ();
  2444:              }
  2445:            }
  2446:            return;
  2447:          case 0x0008:  //R04
  2448:            CRTC.crtR04VFrontEndPort = d & CRTC.crtVerticalMask;
  2449:            {
  2450:              int curr = CRTC.crtR04VFrontEndMask == 0 ? CRTC.crtR04VFrontEndPort : CRTC.crtR04VFrontEndTest;
  2451:              if (CRTC.crtR04VFrontEndCurr != curr) {
  2452:                CRTC.crtR04VFrontEndCurr = curr;
  2453:                if (CRTC.CRT_RASTER_HASH_ON) {
  2454:                  CRTC.crtUpdateRasterHash ();
  2455:                }
  2456:                CRTC.crtRestart ();
  2457:              }
  2458:            }
  2459:            return;
  2460:          case 0x000a:  //R05
  2461:            CRTC.crtR05VSyncEndPort = d & CRTC.crtVerticalMask;
  2462:            {
  2463:              int curr = CRTC.crtR05VSyncEndMask == 0 ? CRTC.crtR05VSyncEndPort : CRTC.crtR05VSyncEndTest;
  2464:              if (CRTC.crtR05VSyncEndCurr != curr) {
  2465:                CRTC.crtR05VSyncEndCurr = curr;
  2466:                CRTC.crtRestart ();
  2467:              }
  2468:            }
  2469:            return;
  2470:          case 0x000c:  //R06
  2471:            CRTC.crtR06VBackEndPort = d & CRTC.crtVerticalMask;
  2472:            {
  2473:              int curr = CRTC.crtR06VBackEndMask == 0 ? CRTC.crtR06VBackEndPort : CRTC.crtR06VBackEndTest;
  2474:              if (CRTC.crtR06VBackEndCurr != curr) {
  2475:                CRTC.crtR06VBackEndCurr = curr;
  2476:                CRTC.crtVDispStart = curr + 1;
  2477:                if (CRTC.CRT_RASTER_HASH_ON) {
  2478:                  CRTC.crtUpdateRasterHash ();
  2479:                }
  2480:                CRTC.crtRestart ();
  2481:              }
  2482:            }
  2483:            return;
  2484:          case 0x000e:  //R07
  2485:            CRTC.crtR07VDispEndPort = d & CRTC.crtVerticalMask;
  2486:            {
  2487:              int curr = CRTC.crtR07VDispEndMask == 0 ? CRTC.crtR07VDispEndPort : CRTC.crtR07VDispEndTest;
  2488:              if (CRTC.crtR07VDispEndCurr != curr) {
  2489:                CRTC.crtR07VDispEndCurr = curr;
  2490:                CRTC.crtVIdleStart = curr + 1;
  2491:                if (CRTC.CRT_RASTER_HASH_ON) {
  2492:                  CRTC.crtUpdateRasterHash ();
  2493:                }
  2494:                CRTC.crtRestart ();
  2495:              }
  2496:            }
  2497:            return;
  2498:          case 0x0010:  //R08
  2499:            d &= 0xff;
  2500:            if (CRTC.crtR08Adjust != d) {
  2501:              CRTC.crtR08Adjust = d;
  2502:              CRTC.crtRestart ();
  2503:            }
  2504:            return;
  2505:          case 0x0012:  //R09
  2506:            CRTC.crtR09IRQRasterPort = d & CRTC.crtVerticalMask;
  2507:            {
  2508:              int curr = CRTC.crtR09IRQRasterMask == 0 ? CRTC.crtR09IRQRasterPort : CRTC.crtR09IRQRasterTest;
  2509:              if (CRTC.crtR09IRQRasterCurr != curr) {
  2510:                CRTC.crtR09IRQRasterCurr = curr;
  2511:                if (CRTC.CRT_RASTER_HASH_ON) {
  2512:                  CRTC.crtUpdateRasterHash ();
  2513:                }
  2514:                if (RasterBreakPoint.RBP_ON) {
  2515:                  RasterBreakPoint.rbpCheckIRQ ();
  2516:                }
  2517:              }
  2518:            }
  2519:            return;
  2520:          case 0x0014:  //R10
  2521:            CRTC.crtR10TxXPort = d & 0x03ff;
  2522:            {
  2523:              int curr = CRTC.crtR10TxXMask == 0 ? CRTC.crtR10TxXPort : CRTC.crtR10TxXTest;
  2524:              if (CRTC.crtR10TxXCurr != curr) {
  2525:                CRTC.crtR10TxXCurr = curr;
  2526:                CRTC.crtAllStamp += 2;
  2527:              }
  2528:            }
  2529:            return;
  2530:          case 0x0016:  //R11
  2531:            CRTC.crtR11TxYPort = d & 0x03ff;
  2532:            {
  2533:              int curr = CRTC.crtR11TxYMask == 0 ? CRTC.crtR11TxYPort : CRTC.crtR11TxYTest;
  2534:              if (CRTC.crtR11TxYCurr != curr) {
  2535:                CRTC.crtR11TxYCurr = curr;
  2536:                //CRTC.crtAllStamp += 2;  //ラッチするとき更新する
  2537:              }
  2538:            }
  2539:            return;
  2540:          case 0x0018:  //R12
  2541:          case 0x001c:  //R14
  2542:          case 0x0020:  //R16
  2543:          case 0x0024:  //R18
  2544:            {
  2545:              int p = (aa - 0x0018) >> 2;  //0,1,2,3
  2546:              CRTC.crtR12GrXPort[p] = d & (p == 0 ? 0x03ff : 0x01ff);
  2547:              int curr = CRTC.crtR12GrXMask[p] == 0 ? CRTC.crtR12GrXPort[p] : CRTC.crtR12GrXTest[p];
  2548:              if (CRTC.crtR12GrXCurr[p] != curr) {
  2549:                CRTC.crtR12GrXCurr[p] = curr;
  2550:                CRTC.crtAllStamp += 2;
  2551:              }
  2552:            }
  2553:            return;
  2554:          case 0x001a:  //R13
  2555:          case 0x001e:  //R15
  2556:          case 0x0022:  //R17
  2557:          case 0x0026:  //R19
  2558:            {
  2559:              int p = (aa - 0x0018) >> 2;  //0,1,2,3
  2560:              CRTC.crtR13GrYPort[p] = d & (p == 0 ? 0x03ff : 0x01ff);
  2561:              int curr = CRTC.crtR13GrYMask[p] == 0 ? CRTC.crtR13GrYPort[p] : CRTC.crtR13GrYTest[p];
  2562:              if (CRTC.crtR13GrYCurr[p] != curr) {
  2563:                CRTC.crtR13GrYCurr[p] = curr;
  2564:                //CRTC.crtAllStamp += 2;  //ラッチするとき更新する
  2565:              }
  2566:            }
  2567:            return;
  2568:          case 0x0028:  //R20
  2569:            CRTC.crtSetMemoryMode (d >> 12, d >> 11, d >> 8);
  2570:            CRTC.crtHighResoPort = d >>> 4 & 1;
  2571:            CRTC.crtVResoPort    = d >>> 2 & 3;
  2572:            CRTC.crtHResoPort    = d       & 3;
  2573:            SpriteScreen.sprAccessible = (d & 0b10010) != 0b10010;
  2574:            int highResoCurr = CRTC.crtHighResoMask == 0 ? CRTC.crtHighResoPort : CRTC.crtHighResoTest;
  2575:            int vResoCurr = CRTC.crtVResoMask == 0 ? CRTC.crtVResoPort : CRTC.crtVResoTest;
  2576:            int hResoCurr = CRTC.crtHResoMask == 0 ? CRTC.crtHResoPort : CRTC.crtHResoTest;
  2577:            if (CRTC.crtHighResoCurr != highResoCurr ||
  2578:                CRTC.crtVResoCurr != vResoCurr ||
  2579:                CRTC.crtHResoCurr != hResoCurr) {
  2580:              CRTC.crtHighResoCurr = highResoCurr;
  2581:              CRTC.crtVResoCurr = vResoCurr;
  2582:              CRTC.crtHResoCurr = hResoCurr;
  2583:              CRTC.crtRestart ();
  2584:            }
  2585:            return;
  2586:          case 0x002a:  //R21
  2587:            CRTC.crtBitMask   = d << 22 < 0;  //(d & 512) != 0
  2588:            CRTC.crtSimAccess = d << 23 < 0;  //(d & 256) != 0
  2589:            CRTC.crtSimPlane3 = (byte) d < 0;  //(d & 128) != 0。d << 24 < 0
  2590:            CRTC.crtSimPlane2 = d << 25 < 0;  //(d & 64) != 0
  2591:            CRTC.crtSimPlane1 = d << 26 < 0;  //(d & 32) != 0
  2592:            CRTC.crtSimPlane0 = d << 27 < 0;  //(d & 16) != 0
  2593:            CRTC.crtCCPlane3  = XEiJ.TEST_BIT_3_SHIFT ? d << 31 - 3 < 0 : (d & 8) != 0;
  2594:            CRTC.crtCCPlane2  = XEiJ.TEST_BIT_2_SHIFT ? d << 31 - 2 < 0 : (d & 4) != 0;
  2595:            CRTC.crtCCPlane1  = XEiJ.TEST_BIT_1_SHIFT ? d << 31 - 1 < 0 : (d & 2) != 0;
  2596:            CRTC.crtCCPlane0  = XEiJ.TEST_BIT_0_SHIFT ? d << 31 - 0 < 0 : (d & 1) != 0;
  2597:            return;
  2598:          case 0x002c:  //R22
  2599:            CRTC.crtR22SrcBlock = d >> 8 & 0xff;
  2600:            CRTC.crtR22DstBlock = d      & 0xff;
  2601:            return;
  2602:          case 0x002e:  //R23
  2603:            CRTC.crtR23Mask = (char) d;
  2604:            return;
  2605:            //case 0x0030:  //R24
  2606:            //case 0x0032:  //R25
  2607:            //case 0x0034:  //R26
  2608:            //case 0x0036:  //R27
  2609:            //case 0x0038:  //R28
  2610:            //case 0x003a:  //R29
  2611:            //case 0x003c:  //R30
  2612:            //case 0x003e:  //R31
  2613:          default:
  2614:            return;
  2615:          }
  2616:        } else {  //$00E80400~$00E807FF
  2617:          aa &= 0xff;  //$00E80500~$00E807FF→$00E80400~$00E804FF
  2618:          if (aa < 0x80) {  //$00E80400~$00E8047F
  2619:            super.mmdWw (a, d);  //バスエラー
  2620:          } else {  //$00E80480~$00E804FF  動作ポート
  2621:            boolean rasterCopyOn = (d & 8) != 0;
  2622:            if (CRTC.crtRasterCopyOn != rasterCopyOn) {
  2623:              CRTC.crtRasterCopyOn = rasterCopyOn;  //ラスタコピー
  2624:              if (CRTC.CRT_RASTER_HASH_ON) {
  2625:                CRTC.crtUpdateRasterHash ();
  2626:              }
  2627:            }
  2628:            CRTC.crtClearStandby = (d & 2) != 0;  //高速クリア
  2629:            return;
  2630:          }
  2631:        }
  2632:      }
  2633:     @Override protected void mmdWl (int a, int d) throws M68kException {
  2634:        mmdWw (a    , d >> 16);
  2635:        mmdWw (a + 2, d      );
  2636:      }
  2637:   },  //MMD_CRT
  2638: 
  2639:   //--------------------------------------------------------------------------------
  2640:   //MMD_VCN ビデオコントローラ
  2641:   //
  2642:   //  $00E82000~$00E821FF  ワードレジスタ
  2643:   //  $00E82200~$00E823FF  ワードレジスタ
  2644:   //  $00E82400~$00E82401  ワードレジスタ
  2645:   //  $00E82402~$00E824FF  $00E82400~$00E82401の繰り返し
  2646:   //  $00E82500~$00E82501  ワードレジスタ
  2647:   //  $00E82502~$00E825FF  $00E82500~$00E82501の繰り返し
  2648:   //  $00E82600~$00E82601  ワードレジスタ
  2649:   //  $00E82602~$00E826FF  $00E82600~$00E82601の繰り返し
  2650:   //  $00E82700~$00E82FFF  $0000
  2651:   //  $00E83000~$00E83FFF  $00E82000~$00E82FFFの繰り返し
  2652:   //
  2653:   MMD_VCN {
  2654:     @Override public String toString () {
  2655:       return Multilingual.mlnJapanese ? "ビデオコントローラ" : "Video Controller";
  2656:     }
  2657:     //リード
  2658:     @Override protected int mmdRbz (int a) throws M68kException {
  2659:        int aa = a & 0x1fff;  //$00E83000~$00E83FFF→$00E82000~$00E82FFF
  2660:        if (aa < 0x0400) {  //パレット
  2661:          XEiJ.mpuClockTime += XEiJ.busWaitTime.palet;
  2662:          int d = (aa < 0x0200 ? VideoController.vcnPal16G8[aa >> 1] :  //$00E82000~$00E821FF  グラフィック
  2663:                   VideoController.vcnPal16TS[(aa - 0x0200) >> 1]);  //$00E82200~$00E823FF  テキストスプライト
  2664:          return (aa & 1) == 0 ? d >> 8 : d & 0xff;
  2665:        } else {  //レジスタ
  2666:          XEiJ.mpuClockTime += XEiJ.busWaitTime.vicon;
  2667:          int d = (aa < 0x0500 ? VideoController.vcnReg1Port :  //$00E82400~$00E824FF
  2668:                   aa < 0x0600 ? VideoController.vcnReg2Port :  //$00E82500~$00E825FF
  2669:                   aa < 0x0700 ? VideoController.vcnReg3Port :  //$00E82600~$00E826FF
  2670:                   0);  //$00E82700~$00E82FFF
  2671:          return (aa & 1) == 0 ? d >> 8 : d & 0xff;
  2672:        }
  2673:      }
  2674:     @Override protected int mmdRwz (int a) throws M68kException {
  2675:        int aa = a & 0x1fff;  //$00E83000~$00E83FFF→$00E82000~$00E82FFF
  2676:        if (aa < 0x0400) {  //パレット
  2677:          XEiJ.mpuClockTime += XEiJ.busWaitTime.palet;
  2678:          return (aa < 0x0200 ? VideoController.vcnPal16G8[aa >> 1] :  //$00E82000~$00E821FF  グラフィックスパレット
  2679:                  VideoController.vcnPal16TS[(aa - 0x0200) >> 1]);  //$00E82200~$00E823FF  テキストスプライトパレット
  2680:        } else {  //レジスタ
  2681:          XEiJ.mpuClockTime += XEiJ.busWaitTime.vicon;
  2682:          return (aa < 0x0500 ? VideoController.vcnReg1Port :  //$00E82400~$00E824FF
  2683:                  aa < 0x0600 ? VideoController.vcnReg2Port :  //$00E82500~$00E825FF
  2684:                  aa < 0x0700 ? VideoController.vcnReg3Port :  //$00E82600~$00E826FF
  2685:                  0);  //$00E82700~$00E82FFF
  2686:        }
  2687:      }
  2688:     @Override protected int mmdRls (int a) throws M68kException {
  2689:        return mmdRwz (a) << 16 | mmdRwz (a + 2);
  2690:      }
  2691:     //ライト
  2692:     @Override protected void mmdWb (int a, int d) throws M68kException {
  2693:        int aa = a & 0x1fff;  //$00E83000~$00E83FFF→$00E82000~$00E82FFF
  2694:        if (aa < 0x0200) {  //$00E82000~$00E821FF  グラフィックスパレット
  2695:          XEiJ.mpuClockTime += XEiJ.busWaitTime.palet;
  2696:          d &= 0xff;
  2697:          int n = aa >> 1;
  2698:          if ((aa & 1) == 0) {  //a=0,2,4,6,8,10,12,14
  2699:            VideoController.vcnPal32G8[n] = VideoController.vcnPalTbl[
  2700:              VideoController.vcnPal16G8[n] = d << 8 | (VideoController.vcnPal16G8[n] & 0xff)
  2701:              ];
  2702:            if ((n & 1) == 0) {  //a=0,4,8,12 n=0,2,4,6
  2703:              VideoController.vcnPal8G16L[n] = d;
  2704:            } else {  //a=2,6,10,14 n-1=0,2,4,6
  2705:              VideoController.vcnPal8G16H[n - 1] = d << 8;
  2706:            }
  2707:          } else {  //a=1,3,5,7,9,11,13,15
  2708:            VideoController.vcnPal32G8[n] = VideoController.vcnPalTbl[
  2709:              VideoController.vcnPal16G8[n] = (VideoController.vcnPal16G8[n] & ~0xff) | d
  2710:              ];
  2711:            if ((n & 1) == 0) {  //a=1,5,9,13 n+1=1,3,5,7
  2712:              VideoController.vcnPal8G16L[n + 1] = d;
  2713:            } else {  //a=3,7,11,15 n=1,3,5,7
  2714:              VideoController.vcnPal8G16H[n] = d << 8;
  2715:            }
  2716:          }
  2717:          if ((VideoController.vcnReg3Curr & 0x001f) != 0) {  //グラフィックス画面が表示されている
  2718:            CRTC.crtAllStamp += 2;
  2719:          }
  2720:        } else if (aa < 0x0400) {  //$00E82200~$00E823FF  テキストスプライトパレット
  2721:          XEiJ.mpuClockTime += XEiJ.busWaitTime.palet;
  2722:          d &= 0xff;
  2723:          int n = (aa - 0x0200) >> 1;
  2724:          VideoController.vcnPal32TS[n] = VideoController.vcnPalTbl[
  2725:            VideoController.vcnPal16TS[n] = ((aa & 1) == 0 ?
  2726:                                             d << 8 | (VideoController.vcnPal16TS[n] & 0xff) :
  2727:                                             (VideoController.vcnPal16TS[n] & ~0xff) | d)
  2728:            ];
  2729:          if ((VideoController.vcnReg3Curr << 31 - 6 < 0 && SpriteScreen.sprReg4BgCtrlCurr << 31 - 9 < 0) ||  //スプライト画面が表示されている
  2730:              (VideoController.vcnReg3Curr << 31 - 5 < 0 && n < 16)) {  //テキスト画面が表示されていてテキストパレットが操作された
  2731:            CRTC.crtAllStamp += 2;
  2732:          }
  2733:        } else if (aa < 0x0500) {  //$00E82400~$00E824FF
  2734:          XEiJ.mpuClockTime += XEiJ.busWaitTime.vicon;
  2735:          d = (aa & 1) == 0 ? 0x00 : d & 0x07;
  2736:          if (VideoController.vcnReg1Port != d) {
  2737:            VideoController.vcnReg1Port = d;
  2738:            VideoController.vcnReg1Curr = ((VideoController.vcnReg1Port & ~VideoController.vcnReg1Mask) |
  2739:                                           (VideoController.vcnReg1Test & VideoController.vcnReg1Mask));
  2740:            VideoController.vcnUpdateMode ();
  2741:          }
  2742:        } else if (aa < 0x0600) {  //$00E82500~$00E825FF
  2743:          XEiJ.mpuClockTime += XEiJ.busWaitTime.vicon;
  2744:          d = ((aa & 1) == 0 ?
  2745:               (d & 0x3f) << 8 | (VideoController.vcnReg2Port & 0xff) :
  2746:               (VideoController.vcnReg2Port & ~0xff) | (d & 0xff));
  2747:          if (VideoController.vcnReg2Port != d) {
  2748:            VideoController.vcnReg2Port = d;
  2749:            VideoController.vcnReg2Curr = ((VideoController.vcnReg2Port & ~VideoController.vcnReg2Mask) |
  2750:                                           (VideoController.vcnReg2Test & VideoController.vcnReg2Mask));
  2751:            VideoController.vcnUpdateMode ();
  2752:          }
  2753:        } else if (aa < 0x0700) {  //$00E82600~$00E826FF
  2754:          XEiJ.mpuClockTime += XEiJ.busWaitTime.vicon;
  2755:          d = ((aa & 1) == 0 ?
  2756:               (d & 0xff) << 8 | (VideoController.vcnReg3Port & 0xff) :
  2757:               (VideoController.vcnReg3Port & ~0xff) | (d & 0xff));
  2758:          if (VideoController.vcnReg3Port != d) {
  2759:            VideoController.vcnReg3Port = d;
  2760:            VideoController.vcnReg3Curr = ((VideoController.vcnReg3Port & ~VideoController.vcnReg3Mask) |
  2761:                                           (VideoController.vcnReg3Test & VideoController.vcnReg3Mask));
  2762:            VideoController.vcnUpdateMode ();
  2763:          }
  2764:        } else {  //$00E82700~$00E82FFF
  2765:          XEiJ.mpuClockTime += XEiJ.busWaitTime.vicon;
  2766:        }
  2767:      }
  2768:     @Override protected void mmdWw (int a, int d) throws M68kException {
  2769:        int aa = a & 0x1fff;  //$00E83000~$00E83FFF→$00E82000~$00E82FFF
  2770:        if (aa < 0x0200) {  //$00E82000~$00E821FF  グラフィックスパレット
  2771:          XEiJ.mpuClockTime += XEiJ.busWaitTime.palet;
  2772:          int n = aa >> 1;  //a=0,2,4,6,8,10,12,14 n=0,1,2,3,4,5,6,7
  2773:          VideoController.vcnPal32G8[n] = VideoController.vcnPalTbl[
  2774:            VideoController.vcnPal16G8[n] = (char) d
  2775:            ];
  2776:          if ((n & 1) == 0) {  //a=0,4,8,12 n=0,2,4,6 n+1=1,3,5,7
  2777:            VideoController.vcnPal8G16L[n] = d >> 8 & 0xff;
  2778:            VideoController.vcnPal8G16L[n + 1] = d & 0xff;
  2779:          } else {  //a=2,4,6,8 n-1=0,2,4,6 n=1,3,5,7
  2780:            VideoController.vcnPal8G16H[n - 1] = d & 0xff00;
  2781:            VideoController.vcnPal8G16H[n] = (d & 0xff) << 8;
  2782:          }
  2783:          if ((VideoController.vcnReg3Curr & 0x001f) != 0) {  //グラフィックス画面が表示されている
  2784:            CRTC.crtAllStamp += 2;
  2785:          }
  2786:        } else if (aa < 0x0400) {  //$00E82200~$00E823FF  テキストスプライトパレット
  2787:          XEiJ.mpuClockTime += XEiJ.busWaitTime.palet;
  2788:          int n = (aa - 0x0200) >> 1;
  2789:          VideoController.vcnPal32TS[n] = VideoController.vcnPalTbl[
  2790:            VideoController.vcnPal16TS[n] = (char) d
  2791:            ];
  2792:          if ((VideoController.vcnReg3Curr << 31 - 6 < 0 && SpriteScreen.sprReg4BgCtrlCurr << 31 - 9 < 0) ||  //スプライト画面が表示されている
  2793:              (VideoController.vcnReg3Curr << 31 - 5 < 0 && n < 16)) {  //テキスト画面が表示されていてテキストパレットが操作された
  2794:            CRTC.crtAllStamp += 2;
  2795:          }
  2796:        } else if (aa < 0x0500) {  //$00E82400~$00E824FF
  2797:          XEiJ.mpuClockTime += XEiJ.busWaitTime.vicon;
  2798:          d &= 0x0007;
  2799:          if (VideoController.vcnReg1Port != d) {
  2800:            VideoController.vcnReg1Port = d;
  2801:            VideoController.vcnReg1Curr = ((VideoController.vcnReg1Port & ~VideoController.vcnReg1Mask) |
  2802:                                           (VideoController.vcnReg1Test & VideoController.vcnReg1Mask));
  2803:            VideoController.vcnUpdateMode ();
  2804:          }
  2805:        } else if (aa < 0x0600) {  //$00E82500~$00E825FF
  2806:          XEiJ.mpuClockTime += XEiJ.busWaitTime.vicon;
  2807:          d &= 0x3fff;
  2808:          if (VideoController.vcnReg2Port != d) {
  2809:            VideoController.vcnReg2Port = d;
  2810:            VideoController.vcnReg2Curr = ((VideoController.vcnReg2Port & ~VideoController.vcnReg2Mask) |
  2811:                                           (VideoController.vcnReg2Test & VideoController.vcnReg2Mask));
  2812:            VideoController.vcnUpdateMode ();
  2813:          }
  2814:        } else if (aa < 0x0700) {  //$00E82600~$00E826FF
  2815:          XEiJ.mpuClockTime += XEiJ.busWaitTime.vicon;
  2816:          d &= 0xffff;
  2817:          if (VideoController.vcnReg3Port != d) {
  2818:            VideoController.vcnReg3Port = d;
  2819:            VideoController.vcnReg3Curr = ((VideoController.vcnReg3Port & ~VideoController.vcnReg3Mask) |
  2820:                                           (VideoController.vcnReg3Test & VideoController.vcnReg3Mask));
  2821:            VideoController.vcnUpdateMode ();
  2822:          }
  2823:        } else {  //$00E82700~$00E82FFF
  2824:          XEiJ.mpuClockTime += XEiJ.busWaitTime.vicon;
  2825:        }
  2826:      }
  2827:     @Override protected void mmdWl (int a, int d) throws M68kException {
  2828:        mmdWw (a    , d >> 16);
  2829:        mmdWw (a + 2, d      );
  2830:      }
  2831:   },  //MMD_VCN
  2832: 
  2833:   //--------------------------------------------------------------------------------
  2834:   //MMD_DMA DMAコントローラ
  2835:   //
  2836:   //  $00E84000~$00E8403F  ワードまたはロングワードレジスタ(CH0)
  2837:   //  $00E84040~$00E8407F  ワードまたはロングワードレジスタ(CH1)
  2838:   //  $00E84080~$00E840BF  ワードまたはロングワードレジスタ(CH2)
  2839:   //  $00E840C0~$00E840FF  ワードまたはロングワードレジスタ(CH4)
  2840:   //  $00E84100~$00E85FFF  $00E84000~$00E840FFの繰り返し
  2841:   //
  2842:   MMD_DMA {
  2843:     @Override public String toString () {
  2844:       return Multilingual.mlnJapanese ? "DMA コントローラ" : "DMA Controller";
  2845:     }
  2846:     //リード
  2847:     @Override protected int mmdRbz (int a) throws M68kException {
  2848:        XEiJ.mpuClockTime += XEiJ.busWaitTime.dmac;
  2849:        return HD63450.dmaReadByte (a);
  2850:      }
  2851:     @Override protected int mmdRwz (int a) throws M68kException {
  2852:        XEiJ.mpuClockTime += XEiJ.busWaitTime.dmac;
  2853:        return HD63450.dmaReadWord (a);
  2854:      }
  2855:     @Override protected int mmdRls (int a) throws M68kException {
  2856:        XEiJ.mpuClockTime += XEiJ.busWaitTime.dmac * 2;
  2857:        return HD63450.dmaReadLong (a);
  2858:      }
  2859:     //ライト
  2860:     @Override protected void mmdWb (int a, int d) throws M68kException {
  2861:        XEiJ.mpuClockTime += XEiJ.busWaitTime.dmac;
  2862:        HD63450.dmaWriteByte (a, d);
  2863:        return;
  2864:      }
  2865:     @Override protected void mmdWw (int a, int d) throws M68kException {
  2866:        XEiJ.mpuClockTime += XEiJ.busWaitTime.dmac;
  2867:        HD63450.dmaWriteWord (a, d);
  2868:        return;
  2869:      }
  2870:     @Override protected void mmdWl (int a, int d) throws M68kException {
  2871:        XEiJ.mpuClockTime += XEiJ.busWaitTime.dmac * 2;
  2872:        HD63450.dmaWriteLong (a, d);
  2873:        return;
  2874:      }
  2875:   },  //MMD_DMA
  2876: 
  2877:   //--------------------------------------------------------------------------------
  2878:   //MMD_SVS スーパーバイザ領域設定
  2879:   //
  2880:   //  $00E86000  バイトアクセスはバスエラー。ワードリードはバスエラー。ワードライトは$??xx
  2881:   //  $00E86001  バイトリードはバスエラー。バイトライトは$xx
  2882:   //  $00E86002~$00E87FFF  $00E86000~$00E86001の繰り返し
  2883:   //
  2884:   MMD_SVS {
  2885:     @Override public String toString () {
  2886:       return Multilingual.mlnJapanese ? "スーパーバイザ領域設定" : "Supervisor Area Setting";
  2887:     }
  2888:     //ライト
  2889:     @Override protected void mmdWb (int a, int d) throws M68kException {
  2890:        if ((a & 1) == 0) {  //偶数アドレスへのバイトライト
  2891:          super.mmdWb (a, d);  //バスエラー
  2892:        } else {  //奇数アドレスへのバイトライト
  2893:          XEiJ.mpuClockTime += XEiJ.busWaitTime.sysport;  //!!!
  2894:          MainMemory.mmrSetSupervisorArea (d);
  2895:        }
  2896:      }
  2897:     @Override protected void mmdWw (int a, int d) throws M68kException {
  2898:        mmdWb (a + 1, d);
  2899:      }
  2900:     @Override protected void mmdWl (int a, int d) throws M68kException {
  2901:        mmdWw (a, d >> 16);
  2902:        mmdWw (a + 2, d);
  2903:      }
  2904:   },  //MMD_SVS
  2905: 
  2906:   //--------------------------------------------------------------------------------
  2907:   //MMD_MFP MFP
  2908:   //
  2909:   //  $00E88000~$00E8803F(偶数)  バイトアクセスはバスエラー。ワードリードは$FFxx。ワードライトは$??xx
  2910:   //  $00E88000~$00E8803F(奇数)  バイトレジスタ
  2911:   //  $00E88040~$00E89FFF  $00E88000~$00E8803Fの繰り返し
  2912:   //
  2913:   MMD_MFP {
  2914:     @Override public String toString () {
  2915:       return Multilingual.mlnJapanese ? "MFP" : "MFP";  //Multi Function Peripheral
  2916:     }
  2917:     //ピーク
  2918:     @Override protected int mmdPbz (int a) {
  2919:       try {
  2920:         return (a & (XEiJ.BUS_MOTHER_MASK & 0xffff803f)) == MC68901.MFP_UDR ? MC68901.mfpUdrQueueArray[MC68901.mfpUdrQueueRead] : mmdRbz (a);
  2921:       } catch (M68kException e) {
  2922:       }
  2923:       return 0;
  2924:     }
  2925:     //リード
  2926:     @Override protected int mmdRbz (int a) throws M68kException {
  2927:        XEiJ.mpuClockTime += XEiJ.busWaitTime.mfp;
  2928:        switch (a & (XEiJ.BUS_MOTHER_MASK & 0xffff803f)) {  //$00E88040~$00E89FFF→$00E88000~$00E8803F
  2929:        case MC68901.MFP_GPIP_DATA:
  2930:          return MC68901.mfpGpipHsync | MC68901.mfpGpipRint | 0b00100000 | MC68901.mfpGpipVdisp | MC68901.mfpGpipOpmirq | MC68901.mfpGpipPower | MC68901.mfpGpipExpwon | MC68901.mfpGpipAlarm;  //GPIP5は常に1
  2931:        case MC68901.MFP_AER:
  2932:          return MC68901.mfpAer;
  2933:        case MC68901.MFP_DDR:
  2934:          return 0x00;
  2935:        case MC68901.MFP_IERA:
  2936:          return MC68901.mfpIer >>> 8;
  2937:        case MC68901.MFP_IERB:
  2938:          return MC68901.mfpIer & 0xff;
  2939:        case MC68901.MFP_IPRA:
  2940:          return ((MC68901.mfpInnerRequest[15] != MC68901.mfpInnerAcknowledged[15] ? 0b10000000 : 0) |
  2941:                  (MC68901.mfpInnerRequest[14] != MC68901.mfpInnerAcknowledged[14] ? 0b01000000 : 0) |
  2942:                  (MC68901.mfpInnerRequest[13] != MC68901.mfpInnerAcknowledged[13] ? 0b00100000 : 0) |
  2943:                  (MC68901.mfpInnerRequest[12] != MC68901.mfpInnerAcknowledged[12] ? 0b00010000 : 0) |
  2944:                  (MC68901.mfpInnerRequest[11] != MC68901.mfpInnerAcknowledged[11] ? 0b00001000 : 0) |
  2945:                  (MC68901.mfpInnerRequest[10] != MC68901.mfpInnerAcknowledged[10] ? 0b00000100 : 0) |
  2946:                  (MC68901.mfpInnerRequest[ 9] != MC68901.mfpInnerAcknowledged[ 9] ? 0b00000010 : 0) |
  2947:                  (MC68901.mfpInnerRequest[ 8] != MC68901.mfpInnerAcknowledged[ 8] ? 0b00000001 : 0));
  2948:        case MC68901.MFP_IPRB:
  2949:          return ((MC68901.mfpInnerRequest[ 7] != MC68901.mfpInnerAcknowledged[ 7] ? 0b10000000 : 0) |
  2950:                  (MC68901.mfpInnerRequest[ 6] != MC68901.mfpInnerAcknowledged[ 6] ? 0b01000000 : 0) |
  2951:                  (MC68901.mfpInnerRequest[ 5] != MC68901.mfpInnerAcknowledged[ 5] ? 0b00100000 : 0) |
  2952:                  (MC68901.mfpInnerRequest[ 4] != MC68901.mfpInnerAcknowledged[ 4] ? 0b00010000 : 0) |
  2953:                  (MC68901.mfpInnerRequest[ 3] != MC68901.mfpInnerAcknowledged[ 3] ? 0b00001000 : 0) |
  2954:                  (MC68901.mfpInnerRequest[ 2] != MC68901.mfpInnerAcknowledged[ 2] ? 0b00000100 : 0) |
  2955:                  (MC68901.mfpInnerRequest[ 1] != MC68901.mfpInnerAcknowledged[ 1] ? 0b00000010 : 0) |
  2956:                  (MC68901.mfpInnerRequest[ 0] != MC68901.mfpInnerAcknowledged[ 0] ? 0b00000001 : 0));
  2957:        case MC68901.MFP_ISRA:
  2958:          return ((MC68901.mfpInnerInService[15] ? 0b10000000 : 0) |
  2959:                  (MC68901.mfpInnerInService[14] ? 0b01000000 : 0) |
  2960:                  (MC68901.mfpInnerInService[13] ? 0b00100000 : 0) |
  2961:                  (MC68901.mfpInnerInService[12] ? 0b00010000 : 0) |
  2962:                  (MC68901.mfpInnerInService[11] ? 0b00001000 : 0) |
  2963:                  (MC68901.mfpInnerInService[10] ? 0b00000100 : 0) |
  2964:                  (MC68901.mfpInnerInService[ 9] ? 0b00000010 : 0) |
  2965:                  (MC68901.mfpInnerInService[ 8] ? 0b00000001 : 0));
  2966:        case MC68901.MFP_ISRB:
  2967:          return ((MC68901.mfpInnerInService[ 7] ? 0b10000000 : 0) |
  2968:                  (MC68901.mfpInnerInService[ 6] ? 0b01000000 : 0) |
  2969:                  (MC68901.mfpInnerInService[ 5] ? 0b00100000 : 0) |
  2970:                  (MC68901.mfpInnerInService[ 4] ? 0b00010000 : 0) |
  2971:                  (MC68901.mfpInnerInService[ 3] ? 0b00001000 : 0) |
  2972:                  (MC68901.mfpInnerInService[ 2] ? 0b00000100 : 0) |
  2973:                  (MC68901.mfpInnerInService[ 1] ? 0b00000010 : 0) |
  2974:                  (MC68901.mfpInnerInService[ 0] ? 0b00000001 : 0));
  2975:        case MC68901.MFP_IMRA:
  2976:          return MC68901.mfpImr >>> 8;
  2977:        case MC68901.MFP_IMRB:
  2978:          return MC68901.mfpImr & 0xff;
  2979:        case MC68901.MFP_VECTOR:
  2980:          return MC68901.mfpVectorHigh;
  2981:        case MC68901.MFP_TACR:
  2982:          return (MC68901.mfpTaEventcount ? 0x08 : 0) | MC68901.mfpTaPrescale;
  2983:        case MC68901.MFP_TBCR:
  2984:          return (MC68901.mfpTbEventcount ? 0x08 : 0) | MC68901.mfpTbPrescale;
  2985:        case MC68901.MFP_TCDCR:
  2986:          return MC68901.mfpTcPrescale << 4 | MC68901.mfpTdPrescale;
  2987:        case MC68901.MFP_TADR:
  2988:          if (MC68901.mfpTaEventcount || MC68901.mfpTaPrescale == 0) {
  2989:            return MC68901.mfpTaCurrent & 0xff;
  2990:          }
  2991:          return MC68901.mfpTaInitial - (int) (Math.floor ((double) (XEiJ.mpuClockTime - MC68901.mfpTaStart) / MC68901.mfpTaDelta) % MC68901.mfpTaInitial) & 0xff;
  2992:        case MC68901.MFP_TBDR:
  2993:          if (MC68901.mfpTbEventcount || MC68901.mfpTbPrescale == 0) {
  2994:            return MC68901.mfpTbCurrent & 0xff;
  2995:          }
  2996:          return MC68901.mfpTbInitial - (int) (Math.floor ((double) (XEiJ.mpuClockTime - MC68901.mfpTbStart) / MC68901.mfpTbDelta) % MC68901.mfpTbInitial) & 0xff;
  2997:        case MC68901.MFP_TCDR:
  2998:          if (MC68901.mfpTcPrescale == 0) {
  2999:            return MC68901.mfpTcCurrent & 0xff;
  3000:          }
  3001:          return MC68901.mfpTcInitial - (int) (Math.floor ((double) (XEiJ.mpuClockTime - MC68901.mfpTcStart) / MC68901.mfpTcDelta) % MC68901.mfpTcInitial) & 0xff;
  3002:        case MC68901.MFP_TDDR:
  3003:          if (MC68901.mfpTdPrescale == 0) {
  3004:            return MC68901.mfpTdCurrent & 0xff;
  3005:          }
  3006:          return MC68901.mfpTdInitial - (int) (Math.floor ((double) (XEiJ.mpuClockTime - MC68901.mfpTdStart) / MC68901.mfpTdDelta) % MC68901.mfpTdInitial) & 0xff;
  3007:        case MC68901.MFP_SYNC_CHAR:
  3008:          return 0;
  3009:        case MC68901.MFP_UCR:
  3010:          return 0;
  3011:        case MC68901.MFP_RSR:
  3012:          if (MC68901.MFP_KBD_ON) {
  3013:            return MC68901.mfpKbdReadPointer != MC68901.mfpKbdWritePointer ? 0x80 : 0;
  3014:          } else {
  3015:            return MC68901.mfpUdrQueueRead != MC68901.mfpUdrQueueWrite ? 0x80 : 0;
  3016:          }
  3017:        case MC68901.MFP_TSR:
  3018:          return 0x80;  //バッファエンプティ
  3019:        case MC68901.MFP_UDR:
  3020:          if (MC68901.MFP_KBD_ON) {
  3021:            return MC68901.mfpKbdReadData ();
  3022:          } else {
  3023:            if (MC68901.mfpUdrQueueRead != MC68901.mfpUdrQueueWrite) {  //キューが空でないとき
  3024:              MC68901.mfpUdrQueueRead = MC68901.mfpUdrQueueRead + 1 & MC68901.MFP_UDR_QUEUE_MASK;
  3025:              if (MC68901.mfpUdrQueueRead != MC68901.mfpUdrQueueWrite) {  //キューが空にならなければ再度割り込み要求を出す
  3026:                if ((MC68901.mfpIer & MC68901.MFP_INPUT_FULL_MASK) != 0) {
  3027:                  MC68901.mfpInnerRequest[MC68901.MFP_INPUT_FULL_LEVEL]++;
  3028:                  if ((MC68901.mfpImr & MC68901.MFP_INPUT_FULL_MASK) != 0) {
  3029:                    if (MC68901.MFP_DELAYED_INTERRUPT) {
  3030:                      XEiJ.mpuDIRR |= XEiJ.MPU_MFP_INTERRUPT_MASK;
  3031:                    } else {
  3032:                      XEiJ.mpuIRR |= XEiJ.MPU_MFP_INTERRUPT_MASK;
  3033:                    }
  3034:                  }
  3035:                }
  3036:              }
  3037:            }
  3038:            return MC68901.mfpUdrQueueArray[MC68901.mfpUdrQueueRead];  //最後に押されたまたは離されたキー
  3039:          }
  3040:        default:
  3041:          if ((a & 1) == 0 &&  //偶数アドレスのバイトリード
  3042:              !XEiJ.currentIsSecond) {  //Xellent30の030モードではない
  3043:            return super.mmdRbz (a);  //バスエラー
  3044:          }
  3045:          return 0xff;
  3046:        }
  3047:      }
  3048:     @Override protected int mmdRwz (int a) throws M68kException {
  3049:        return 0xff00 | mmdRbz (a + 1);
  3050:      }
  3051:     @Override protected int mmdRls (int a) throws M68kException {
  3052:        return mmdRwz (a) << 16 | mmdRwz (a + 2);
  3053:      }
  3054:     //ライト
  3055:     @Override protected void mmdWb (int a, int d) throws M68kException {
  3056:        XEiJ.mpuClockTime += XEiJ.busWaitTime.mfp;
  3057:        switch (a & (XEiJ.BUS_MOTHER_MASK & 0xffff803f)) {  //$00E88040~$00E89FFF→$00E88000~$00E8803F
  3058:        case MC68901.MFP_GPIP_DATA:
  3059:          return;
  3060:        case MC68901.MFP_AER:
  3061:          MC68901.mfpAer = d & 0xff;
  3062:          return;
  3063:        case MC68901.MFP_DDR:
  3064:          return;
  3065:        case MC68901.MFP_IERA:
  3066:          d = (char) (d << 8);
  3067:          int oldIera = MC68901.mfpIer;
  3068:          MC68901.mfpIer = d | (MC68901.mfpIer & 0xff);
  3069:          //MC68901.MFP_IERAのビットに0を書き込むとMC68901.MFP_IPRAの該当ビットも0になる
  3070:          if ((short) d >= 0) {  //(0b10000000_00000000 & d) == 0
  3071:            MC68901.mfpInnerAcknowledged[15] = MC68901.mfpInnerRequest[15];
  3072:          }
  3073:          if (d << 31 - 14 >= 0) {  //(0b01000000_00000000 & d) == 0
  3074:            MC68901.mfpInnerAcknowledged[14] = MC68901.mfpInnerRequest[14];
  3075:          }
  3076:          if (d << 31 - 13 >= 0) {  //(0b00100000_00000000 & d) == 0
  3077:            MC68901.mfpInnerAcknowledged[13] = MC68901.mfpInnerRequest[13];
  3078:          }
  3079:          if (d << 31 - 12 >= 0) {  //(0b00010000_00000000 & d) == 0
  3080:            MC68901.mfpInnerAcknowledged[12] = MC68901.mfpInnerRequest[12];
  3081:          } else if (oldIera << 31 - 12 >= 0 &&  //MC68901.MFP_INPUT_FULL_MASKが0→1
  3082:                     (MC68901.MFP_KBD_ON ?
  3083:                      MC68901.mfpKbdReadPointer != MC68901.mfpKbdWritePointer :  //バッファが空でないとき
  3084:                      MC68901.mfpUdrQueueRead != MC68901.mfpUdrQueueWrite)) {  //キューが空でないとき
  3085:            MC68901.mfpInnerRequest[MC68901.MFP_INPUT_FULL_LEVEL]++;
  3086:            if ((MC68901.mfpImr & MC68901.MFP_INPUT_FULL_MASK) != 0) {
  3087:              //MFPのキー入力割り込みを要求する
  3088:              if (MC68901.MFP_DELAYED_INTERRUPT) {
  3089:                XEiJ.mpuDIRR |= XEiJ.MPU_MFP_INTERRUPT_MASK;
  3090:              } else {
  3091:                XEiJ.mpuIRR |= XEiJ.MPU_MFP_INTERRUPT_MASK;
  3092:              }
  3093:            }
  3094:          }
  3095:          if (d << 31 - 11 >= 0) {  //(0b00001000_00000000 & d) == 0
  3096:            MC68901.mfpInnerAcknowledged[11] = MC68901.mfpInnerRequest[11];
  3097:          }
  3098:          if (d << 31 - 10 >= 0) {  //(0b00000100_00000000 & d) == 0
  3099:            MC68901.mfpInnerAcknowledged[10] = MC68901.mfpInnerRequest[10];
  3100:          }
  3101:          if (d << 31 - 9 >= 0) {  //(0b00000010_00000000 & d) == 0
  3102:            MC68901.mfpInnerAcknowledged[ 9] = MC68901.mfpInnerRequest[ 9];
  3103:          }
  3104:          if (d << 31 - 8 >= 0) {  //(0b00000001_00000000 & d) == 0
  3105:            MC68901.mfpInnerAcknowledged[ 8] = MC68901.mfpInnerRequest[ 8];
  3106:          }
  3107:          return;
  3108:        case MC68901.MFP_IERB:
  3109:          MC68901.mfpIer = (MC68901.mfpIer & ~0xff) | (d & 0xff);
  3110:          //MC68901.MFP_IERBのビットに0を書き込むとMC68901.MFP_IPRBの該当ビットも0になる
  3111:          if ((byte) d >= 0) {  //(0b10000000 & d) == 0
  3112:            MC68901.mfpInnerAcknowledged[ 7] = MC68901.mfpInnerRequest[ 7];
  3113:          }
  3114:          if (d << 31 - 6 >= 0) {  //(0b01000000 & d) == 0
  3115:            MC68901.mfpInnerAcknowledged[ 6] = MC68901.mfpInnerRequest[ 6];
  3116:          }
  3117:          if (d << 31 - 5 >= 0) {  //(0b00100000 & d) == 0
  3118:            MC68901.mfpInnerAcknowledged[ 5] = MC68901.mfpInnerRequest[ 5];
  3119:          }
  3120:          if (d << 31 - 4 >= 0) {  //(0b00010000 & d) == 0
  3121:            MC68901.mfpInnerAcknowledged[ 4] = MC68901.mfpInnerRequest[ 4];
  3122:          }
  3123:          if (XEiJ.TEST_BIT_3_SHIFT ? d << 31 - 3 >= 0 : (d & 8) == 0) {
  3124:            MC68901.mfpInnerAcknowledged[ 3] = MC68901.mfpInnerRequest[ 3];
  3125:          }
  3126:          if (XEiJ.TEST_BIT_2_SHIFT ? d << 31 - 2 >= 0 : (d & 4) == 0) {
  3127:            MC68901.mfpInnerAcknowledged[ 2] = MC68901.mfpInnerRequest[ 2];
  3128:          }
  3129:          if (XEiJ.TEST_BIT_1_SHIFT ? d << 31 - 1 >= 0 : (d & 2) == 0) {
  3130:            MC68901.mfpInnerAcknowledged[ 1] = MC68901.mfpInnerRequest[ 1];
  3131:          }
  3132:          if (XEiJ.TEST_BIT_0_SHIFT ? d << 31 - 0 >= 0 : (d & 1) == 0) {
  3133:            MC68901.mfpInnerAcknowledged[ 0] = MC68901.mfpInnerRequest[ 0];
  3134:          }
  3135:          return;
  3136:        case MC68901.MFP_IPRA:
  3137:          //MC68901.MFP_IPRAのビットは他のすべてのビットに1を書き込むことで直接クリアできる
  3138:          switch (d & 0xff) {
  3139:          case 0b01111111:
  3140:            MC68901.mfpInnerAcknowledged[15] = MC68901.mfpInnerRequest[15];
  3141:            break;
  3142:          case 0b10111111:
  3143:            MC68901.mfpInnerAcknowledged[14] = MC68901.mfpInnerRequest[14];
  3144:            break;
  3145:          case 0b11011111:
  3146:            MC68901.mfpInnerAcknowledged[13] = MC68901.mfpInnerRequest[13];
  3147:            break;
  3148:          case 0b11101111:
  3149:            MC68901.mfpInnerAcknowledged[12] = MC68901.mfpInnerRequest[12];
  3150:            break;
  3151:          case 0b11110111:
  3152:            MC68901.mfpInnerAcknowledged[11] = MC68901.mfpInnerRequest[11];
  3153:            break;
  3154:          case 0b11111011:
  3155:            MC68901.mfpInnerAcknowledged[10] = MC68901.mfpInnerRequest[10];
  3156:            break;
  3157:          case 0b11111101:
  3158:            MC68901.mfpInnerAcknowledged[ 9] = MC68901.mfpInnerRequest[ 9];
  3159:            break;
  3160:          case 0b11111110:
  3161:            MC68901.mfpInnerAcknowledged[ 8] = MC68901.mfpInnerRequest[ 8];
  3162:            break;
  3163:          }
  3164:          return;
  3165:        case MC68901.MFP_IPRB:
  3166:          //MC68901.MFP_IPRBのビットは他のすべてのビットに1を書き込むことで直接クリアできる
  3167:          switch (d & 0xff) {
  3168:          case 0b01111111:
  3169:            MC68901.mfpInnerAcknowledged[ 7] = MC68901.mfpInnerRequest[ 7];
  3170:            break;
  3171:          case 0b10111111:
  3172:            MC68901.mfpInnerAcknowledged[ 6] = MC68901.mfpInnerRequest[ 6];
  3173:            break;
  3174:          case 0b11011111:
  3175:            MC68901.mfpInnerAcknowledged[ 5] = MC68901.mfpInnerRequest[ 5];
  3176:            break;
  3177:          case 0b11101111:
  3178:            MC68901.mfpInnerAcknowledged[ 4] = MC68901.mfpInnerRequest[ 4];
  3179:            break;
  3180:          case 0b11110111:
  3181:            MC68901.mfpInnerAcknowledged[ 3] = MC68901.mfpInnerRequest[ 3];
  3182:            break;
  3183:          case 0b11111011:
  3184:            MC68901.mfpInnerAcknowledged[ 2] = MC68901.mfpInnerRequest[ 2];
  3185:            break;
  3186:          case 0b11111101:
  3187:            MC68901.mfpInnerAcknowledged[ 1] = MC68901.mfpInnerRequest[ 1];
  3188:            break;
  3189:          case 0b11111110:
  3190:            MC68901.mfpInnerAcknowledged[ 0] = MC68901.mfpInnerRequest[ 0];
  3191:            break;
  3192:          }
  3193:          return;
  3194:        case MC68901.MFP_ISRA:
  3195:          //MC68901.MFP_ISRAのビットは他のすべてのビットに1を書き込むことで直接クリアできる
  3196:          switch (d & 0xff) {
  3197:          case 0b01111111:
  3198:            MC68901.mfpInnerInService[15] = false;
  3199:            break;
  3200:          case 0b10111111:
  3201:            MC68901.mfpInnerInService[14] = false;
  3202:            break;
  3203:          case 0b11011111:
  3204:            MC68901.mfpInnerInService[13] = false;
  3205:            break;
  3206:          case 0b11101111:
  3207:            MC68901.mfpInnerInService[12] = false;
  3208:            break;
  3209:          case 0b11110111:
  3210:            MC68901.mfpInnerInService[11] = false;
  3211:            break;
  3212:          case 0b11111011:
  3213:            MC68901.mfpInnerInService[10] = false;
  3214:            break;
  3215:          case 0b11111101:
  3216:            MC68901.mfpInnerInService[ 9] = false;
  3217:            break;
  3218:          case 0b11111110:
  3219:            MC68901.mfpInnerInService[ 8] = false;
  3220:            break;
  3221:          }
  3222:          return;
  3223:        case MC68901.MFP_ISRB:
  3224:          //MC68901.MFP_ISRBのビットは他のすべてのビットに1を書き込むことで直接クリアできる
  3225:          switch (d & 0xff) {
  3226:          case 0b01111111:
  3227:            MC68901.mfpInnerInService[ 7] = false;
  3228:            break;
  3229:          case 0b10111111:
  3230:            MC68901.mfpInnerInService[ 6] = false;
  3231:            break;
  3232:          case 0b11011111:
  3233:            MC68901.mfpInnerInService[ 5] = false;
  3234:            break;
  3235:          case 0b11101111:
  3236:            MC68901.mfpInnerInService[ 4] = false;
  3237:            break;
  3238:          case 0b11110111:
  3239:            MC68901.mfpInnerInService[ 3] = false;
  3240:            break;
  3241:          case 0b11111011:
  3242:            MC68901.mfpInnerInService[ 2] = false;
  3243:            break;
  3244:          case 0b11111101:
  3245:            MC68901.mfpInnerInService[ 1] = false;
  3246:            break;
  3247:          case 0b11111110:
  3248:            MC68901.mfpInnerInService[ 0] = false;
  3249:            break;
  3250:          }
  3251:          return;
  3252:        case MC68901.MFP_IMRA:
  3253:          MC68901.mfpImr = (d & 0xff) << 8 | (MC68901.mfpImr & 0xff);
  3254:          //MC68901.MFP_IMRAのビットに1を書き込んだときMC68901.MFP_IPRAの該当ビットが1ならば割り込み発生
  3255:          if ((byte) d < 0 && MC68901.mfpInnerRequest[15] != MC68901.mfpInnerAcknowledged[15] ||  //(0b10000000 & d) != 0
  3256:              d << 31 - 6 < 0 && MC68901.mfpInnerRequest[14] != MC68901.mfpInnerAcknowledged[14] ||  //(0b01000000 & d) != 0
  3257:              d << 31 - 5 < 0 && MC68901.mfpInnerRequest[13] != MC68901.mfpInnerAcknowledged[13] ||  //(0b00100000 & d) != 0
  3258:              d << 31 - 4 < 0 && MC68901.mfpInnerRequest[12] != MC68901.mfpInnerAcknowledged[12] ||  //(0b00010000 & d) != 0
  3259:              (XEiJ.TEST_BIT_3_SHIFT ? d << 31 - 3 < 0 : (d & 8) != 0) && MC68901.mfpInnerRequest[11] != MC68901.mfpInnerAcknowledged[11] ||
  3260:              (XEiJ.TEST_BIT_2_SHIFT ? d << 31 - 2 < 0 : (d & 4) != 0) && MC68901.mfpInnerRequest[10] != MC68901.mfpInnerAcknowledged[10] ||
  3261:              (XEiJ.TEST_BIT_1_SHIFT ? d << 31 - 1 < 0 : (d & 2) != 0) && MC68901.mfpInnerRequest[ 9] != MC68901.mfpInnerAcknowledged[ 9] ||
  3262:              (XEiJ.TEST_BIT_0_SHIFT ? d << 31 - 0 < 0 : (d & 1) != 0) && MC68901.mfpInnerRequest[ 8] != MC68901.mfpInnerAcknowledged[ 8]) {
  3263:            if (MC68901.MFP_DELAYED_INTERRUPT) {
  3264:              XEiJ.mpuDIRR |= XEiJ.MPU_MFP_INTERRUPT_MASK;
  3265:            } else {
  3266:              XEiJ.mpuIRR |= XEiJ.MPU_MFP_INTERRUPT_MASK;
  3267:            }
  3268:          }
  3269:          return;
  3270:        case MC68901.MFP_IMRB:
  3271:          MC68901.mfpImr = (MC68901.mfpImr & ~0xff) | (d & 0xff);
  3272:          //MC68901.MFP_IMRBのビットに1を書き込んだときMC68901.MFP_IPRBの該当ビットが1ならば割り込み発生
  3273:          if ((byte) d < 0 && MC68901.mfpInnerRequest[ 7] != MC68901.mfpInnerAcknowledged[ 7] ||  //(0b10000000 & d) != 0
  3274:              d << 31 - 6 < 0 && MC68901.mfpInnerRequest[ 6] != MC68901.mfpInnerAcknowledged[ 6] ||  //(0b01000000 & d) != 0
  3275:              d << 31 - 5 < 0 && MC68901.mfpInnerRequest[ 5] != MC68901.mfpInnerAcknowledged[ 5] ||  //(0b00100000 & d) != 0
  3276:              d << 31 - 4 < 0 && MC68901.mfpInnerRequest[ 4] != MC68901.mfpInnerAcknowledged[ 4] ||  //(0b00010000 & d) != 0
  3277:              (XEiJ.TEST_BIT_3_SHIFT ? d << 31 - 3 < 0 : (d & 8) != 0) && MC68901.mfpInnerRequest[ 3] != MC68901.mfpInnerAcknowledged[ 3] ||
  3278:              (XEiJ.TEST_BIT_2_SHIFT ? d << 31 - 2 < 0 : (d & 4) != 0) && MC68901.mfpInnerRequest[ 2] != MC68901.mfpInnerAcknowledged[ 2] ||
  3279:              (XEiJ.TEST_BIT_1_SHIFT ? d << 31 - 1 < 0 : (d & 2) != 0) && MC68901.mfpInnerRequest[ 1] != MC68901.mfpInnerAcknowledged[ 1] ||
  3280:              (XEiJ.TEST_BIT_0_SHIFT ? d << 31 - 0 < 0 : (d & 1) != 0) && MC68901.mfpInnerRequest[ 0] != MC68901.mfpInnerAcknowledged[ 0]) {
  3281:            if (MC68901.MFP_DELAYED_INTERRUPT) {
  3282:              XEiJ.mpuDIRR |= XEiJ.MPU_MFP_INTERRUPT_MASK;
  3283:            } else {
  3284:              XEiJ.mpuIRR |= XEiJ.MPU_MFP_INTERRUPT_MASK;
  3285:            }
  3286:          }
  3287:          return;
  3288:        case MC68901.MFP_VECTOR:
  3289:          MC68901.mfpVectorHigh = 0xf0 & d;  //ビット3は0(全チャンネル自動割込み終了モード)に固定
  3290:          return;
  3291:        case MC68901.MFP_TACR:
  3292:          {
  3293:            int prevPrescale = MC68901.mfpTaPrescale;
  3294:            MC68901.mfpTaEventcount = (d & 0x08) != 0;
  3295:            MC68901.mfpTaPrescale = d & 0x07;
  3296:            if (MC68901.mfpTaEventcount && MC68901.mfpTaPrescale != 0) {  //パルス幅計測モードはキャンセル
  3297:              MC68901.mfpTaEventcount = false;
  3298:              MC68901.mfpTaPrescale = 0;
  3299:            }
  3300:            if (MC68901.mfpTaEventcount) {  //イベントカウントモード
  3301:              if (prevPrescale != 0) {  //ディレイモードで動作中だったとき
  3302:                MC68901.mfpTaCurrent = MC68901.mfpTaInitial - (int) (Math.floor ((double) (XEiJ.mpuClockTime - MC68901.mfpTaStart) / MC68901.mfpTaDelta) % MC68901.mfpTaInitial);
  3303:              }
  3304:              MC68901.mfpTaClock = XEiJ.FAR_FUTURE;
  3305:              TickerQueue.tkqRemove (MC68901.mfpTaTicker);
  3306:            } else if (MC68901.mfpTaPrescale != 0) {  //ディレイモード
  3307:              //! ディレイモードで動作中にプリスケールを変更されるとカウンタが即座に初期値に戻ってしまう
  3308:              MC68901.mfpTaClock = (MC68901.mfpTaStart = XEiJ.mpuClockTime) + (MC68901.mfpTaDelta = MC68901.MFP_DELTA[MC68901.mfpTaPrescale]) * MC68901.mfpTaInitial;
  3309:              TickerQueue.tkqAdd (MC68901.mfpTaTicker, MC68901.mfpTaClock);
  3310:            } else {  //カウント停止
  3311:              if (prevPrescale != 0) {  //ディレイモードで動作中だったとき
  3312:                MC68901.mfpTaCurrent = MC68901.mfpTaInitial - (int) (Math.floor ((double) (XEiJ.mpuClockTime - MC68901.mfpTaStart) / MC68901.mfpTaDelta) % MC68901.mfpTaInitial);
  3313:              }
  3314:              MC68901.mfpTaClock = XEiJ.FAR_FUTURE;
  3315:              TickerQueue.tkqRemove (MC68901.mfpTaTicker);
  3316:            }
  3317:          }
  3318:          return;
  3319:        case MC68901.MFP_TBCR:
  3320:          {
  3321:            int prevPrescale = MC68901.mfpTbPrescale;
  3322:            MC68901.mfpTbEventcount = (d & 0x08) != 0;
  3323:            MC68901.mfpTbPrescale = d & 0x07;
  3324:            MC68901.mfpTbKeyboardOn = !MC68901.mfpTbEventcount && MC68901.mfpTbPrescale == 0x01 && MC68901.mfpTbInitial == 0x0d;
  3325:            if (MC68901.mfpTbEventcount && MC68901.mfpTbPrescale != 0) {  //パルス幅計測モードはキャンセル
  3326:              MC68901.mfpTbEventcount = false;
  3327:              MC68901.mfpTbPrescale = 0;
  3328:            }
  3329:            if (MC68901.mfpTbEventcount) {  //イベントカウントモード
  3330:              if (prevPrescale != 0) {  //ディレイモードで動作中だったとき
  3331:                MC68901.mfpTbCurrent = MC68901.mfpTbInitial - (int) (Math.floor ((double) (XEiJ.mpuClockTime - MC68901.mfpTbStart) / MC68901.mfpTbDelta) % MC68901.mfpTbInitial);
  3332:              }
  3333:              MC68901.mfpTbClock = XEiJ.FAR_FUTURE;
  3334:              TickerQueue.tkqRemove (MC68901.mfpTbTicker);
  3335:            } else if (MC68901.mfpTbPrescale != 0) {  //ディレイモード
  3336:              //! ディレイモードで動作中にプリスケールを変更されるとカウンタが即座に初期値に戻ってしまう
  3337:              MC68901.mfpTbClock = (MC68901.mfpTbStart = XEiJ.mpuClockTime) + (MC68901.mfpTbDelta = MC68901.MFP_DELTA[MC68901.mfpTbPrescale]) * MC68901.mfpTbInitial;
  3338:              TickerQueue.tkqAdd (MC68901.mfpTbTicker, MC68901.mfpTbClock);
  3339:            } else {  //カウント停止
  3340:              if (prevPrescale != 0) {  //ディレイモードで動作中だったとき
  3341:                MC68901.mfpTbCurrent = MC68901.mfpTbInitial - (int) (Math.floor ((double) (XEiJ.mpuClockTime - MC68901.mfpTbStart) / MC68901.mfpTbDelta) % MC68901.mfpTbInitial);
  3342:              }
  3343:              MC68901.mfpTbClock = XEiJ.FAR_FUTURE;
  3344:              TickerQueue.tkqRemove (MC68901.mfpTbTicker);
  3345:            }
  3346:          }
  3347:          return;
  3348:        case MC68901.MFP_TCDCR:
  3349:          {
  3350:            int prevPrescale = MC68901.mfpTcPrescale;
  3351:            MC68901.mfpTcPrescale = d >> 4 & 0x07;
  3352:            if (MC68901.mfpTcPrescale != 0) {  //ディレイモード
  3353:              //! ディレイモードで動作中にプリスケールを変更されるとカウンタが即座に初期値に戻ってしまう
  3354:              MC68901.mfpTcClock = (MC68901.mfpTcStart = XEiJ.mpuClockTime) + (MC68901.mfpTcDelta = MC68901.MFP_DELTA[MC68901.mfpTcPrescale]) * MC68901.mfpTcInitial;
  3355:              TickerQueue.tkqAdd (MC68901.mfpTcTicker, MC68901.mfpTcClock);
  3356:            } else {  //カウント停止
  3357:              if (prevPrescale != 0) {  //ディレイモードで動作中だったとき
  3358:                MC68901.mfpTcCurrent = MC68901.mfpTcInitial - (int) (Math.floor ((double) (XEiJ.mpuClockTime - MC68901.mfpTcStart) / MC68901.mfpTcDelta) % MC68901.mfpTcInitial);
  3359:              }
  3360:              MC68901.mfpTcClock = XEiJ.FAR_FUTURE;
  3361:              TickerQueue.tkqRemove (MC68901.mfpTcTicker);
  3362:            }
  3363:          }
  3364:          {
  3365:            int prevPrescale = MC68901.mfpTdPrescale;
  3366:            MC68901.mfpTdPrescale = d & 0x07;
  3367:            if (MC68901.mfpTdPrescale != 0) {  //ディレイモード
  3368:              //! ディレイモードで動作中にプリスケールを変更されるとカウンタが即座に初期値に戻ってしまう
  3369:              MC68901.mfpTdClock = (MC68901.mfpTdStart = XEiJ.mpuClockTime) + (MC68901.mfpTdDelta = MC68901.MFP_DELTA[MC68901.mfpTdPrescale]) * MC68901.mfpTdInitial;
  3370:              TickerQueue.tkqAdd (MC68901.mfpTdTicker, MC68901.mfpTdClock);
  3371:            } else {  //カウント停止
  3372:              if (prevPrescale != 0) {  //ディレイモードで動作中だったとき
  3373:                MC68901.mfpTdCurrent = MC68901.mfpTdInitial - (int) (Math.floor ((double) (XEiJ.mpuClockTime - MC68901.mfpTdStart) / MC68901.mfpTdDelta) % MC68901.mfpTdInitial);
  3374:              }
  3375:              MC68901.mfpTdClock = XEiJ.FAR_FUTURE;
  3376:              TickerQueue.tkqRemove (MC68901.mfpTdTicker);
  3377:            }
  3378:          }
  3379:          return;
  3380:        case MC68901.MFP_TADR:
  3381:          //! ディレイモードで動作中に初期値を変更するとオーバーフローするまでMC68901.MFP_TADRの値がずれてしまう
  3382:          d &= 0xff;
  3383:          MC68901.mfpTaInitial = d == 0 ? 256 : d;  //初期値
  3384:          if (!MC68901.mfpTaEventcount && MC68901.mfpTaPrescale == 0) {  //動作中でなければカウンタの値も変更される
  3385:            MC68901.mfpTaCurrent = MC68901.mfpTaInitial;
  3386:          }
  3387:          return;
  3388:        case MC68901.MFP_TBDR:
  3389:          //! ディレイモードで動作中に初期値を変更するとオーバーフローするまでMC68901.MFP_TADRの値がずれてしまう
  3390:          d &= 0xff;
  3391:          MC68901.mfpTbInitial = d == 0 ? 256 : d;  //初期値
  3392:          MC68901.mfpTbKeyboardOn = !MC68901.mfpTbEventcount && MC68901.mfpTbPrescale == 0x01 && MC68901.mfpTbInitial == 0x0d;
  3393:          if (!MC68901.mfpTbEventcount && MC68901.mfpTbPrescale == 0) {  //動作中でなければカウンタの値も変更される
  3394:            MC68901.mfpTbCurrent = MC68901.mfpTbInitial;
  3395:          }
  3396:          return;
  3397:        case MC68901.MFP_TCDR:
  3398:          //! ディレイモードで動作中に初期値を変更するとオーバーフローするまでMC68901.MFP_TADRの値がずれてしまう
  3399:          d &= 0xff;
  3400:          MC68901.mfpTcInitial = d == 0 ? 256 : d;  //初期値
  3401:          if (MC68901.mfpTcPrescale == 0) {  //動作中でなければカウンタの値も変更される
  3402:            MC68901.mfpTcCurrent = MC68901.mfpTcInitial;
  3403:          }
  3404:          return;
  3405:        case MC68901.MFP_TDDR:
  3406:          //! ディレイモードで動作中に初期値を変更するとオーバーフローするまでMC68901.MFP_TADRの値がずれてしまう
  3407:          d &= 0xff;
  3408:          MC68901.mfpTdInitial = d == 0 ? 256 : d;  //初期値
  3409:          if (MC68901.mfpTdPrescale == 0) {  //動作中でなければカウンタの値も変更される
  3410:            MC68901.mfpTdCurrent = MC68901.mfpTdInitial;
  3411:          }
  3412:          return;
  3413:        case MC68901.MFP_SYNC_CHAR:
  3414:          return;
  3415:        case MC68901.MFP_UCR:
  3416:          return;
  3417:        case MC68901.MFP_RSR:
  3418:          return;
  3419:        case MC68901.MFP_TSR:
  3420:          return;
  3421:        case MC68901.MFP_UDR:
  3422:          if (!MC68901.mfpTbKeyboardOn) {
  3423:            return;
  3424:          }
  3425:          if ((byte) d < 0) {  //LEDの状態
  3426:            Keyboard.kbdSetLedStatus (d);
  3427:          } else if ((d & 0xf8) == 0x40) {  //MSCTRL
  3428:          } else if ((d & 0xf8) == 0x48) {  //ロック
  3429:          } else if ((d & 0xfc) == 0x54) {  //LEDの明るさ
  3430:            Keyboard.kbdSetLedBrightness (d);
  3431:          } else if ((d & 0xfc) == 0x58) {  //テレビコントロール
  3432:          } else if ((d & 0xfc) == 0x5c) {  //OPT.2キーによるテレビコントロール
  3433:          } else if ((d & 0xf0) == 0x60) {  //リピート開始時間
  3434:            Keyboard.kbdSetRepeatDelay (0x0f & d);
  3435:          } else if ((d & 0xf0) == 0x70) {  //リピート間隔
  3436:            Keyboard.kbdSetRepeatInterval (0x0f & d);
  3437:          }
  3438:          return;
  3439:        default:
  3440:          if ((a & 1) == 0 &&  //偶数アドレスのバイトライト
  3441:              !XEiJ.currentIsSecond) {  //Xellent30の030モードではない
  3442:            super.mmdWb (a, d);  //バスエラー
  3443:          }
  3444:          return;
  3445:        }
  3446:      }
  3447:     @Override protected void mmdWw (int a, int d) throws M68kException {
  3448:        mmdWb (a + 1, d);
  3449:      }
  3450:     @Override protected void mmdWl (int a, int d) throws M68kException {
  3451:        mmdWw (a, d >> 16);
  3452:        mmdWw (a + 2, d);
  3453:      }
  3454:   },  //MMD_MFP
  3455: 
  3456:   //--------------------------------------------------------------------------------
  3457:   //MMD_RTC_FIRST RTC
  3458:   //
  3459:   //  $00E8A000~$00E8A01F(偶数)  バイトアクセスはバスエラー。ワードリードは$FFxx。ワードライトは$??xx
  3460:   //  $00E8A000~$00E8A01F(奇数)  バイトレジスタ
  3461:   //  $00E8A020~$00E8AFFF  $00E8A000~$00E8A01Fの繰り返し
  3462:   //
  3463:   MMD_RTC_FIRST {
  3464:     @Override public String toString () {
  3465:       return Multilingual.mlnJapanese ? "RTC" : "RTC";  //Real-Time Clock
  3466:     }
  3467:     //ピーク
  3468:     @Override protected byte mmdPbs (int a) {
  3469:       return (byte) RP5C15.rtcPeekByte (a);
  3470:     }
  3471:     @Override protected int mmdPbz (int a) {
  3472:       return RP5C15.rtcPeekByte (a);
  3473:     }
  3474:     @Override protected int mmdPws (int a) {
  3475:       return RP5C15.rtcPeekByte (a + 1);
  3476:     }
  3477:     @Override protected int mmdPwz (int a) {
  3478:       return RP5C15.rtcPeekByte (a + 1);
  3479:     }
  3480:     @Override protected int mmdPls (int a) {
  3481:       return (RP5C15.rtcPeekByte (a + 1) << 16 |
  3482:               RP5C15.rtcPeekByte (a + 3));
  3483:     }
  3484:     //リード
  3485:     @Override protected byte mmdRbs (int a) throws M68kException {
  3486:        if ((a & 1) == 0 &&  //偶数アドレスのバイトリード
  3487:            !XEiJ.currentIsSecond) {  //Xellent30の030モードではない
  3488:          return super.mmdRbs (a);  //バスエラー
  3489:        }
  3490:        XEiJ.mpuClockTime += XEiJ.busWaitTime.rtc;
  3491:        XEiJ.busSuper (MemoryMappedDevice.MMD_RTC_NEXT, 0x00e8a000, 0x00e8c000);  //RTC RTC
  3492:        RP5C15.rtcUpdate ();
  3493:        return (byte) RP5C15.rtcReadByte (a);
  3494:      }
  3495:     @Override protected int mmdRbz (int a) throws M68kException {
  3496:        if ((a & 1) == 0 &&  //偶数アドレスのバイトリード
  3497:            !XEiJ.currentIsSecond) {  //Xellent30の030モードではない
  3498:          return super.mmdRbz (a);  //バスエラー
  3499:        }
  3500:        XEiJ.mpuClockTime += XEiJ.busWaitTime.rtc;
  3501:        XEiJ.busSuper (MemoryMappedDevice.MMD_RTC_NEXT, 0x00e8a000, 0x00e8c000);  //RTC RTC
  3502:        RP5C15.rtcUpdate ();
  3503:        return RP5C15.rtcReadByte (a);
  3504:      }
  3505:     @Override protected int mmdRws (int a) throws M68kException {
  3506:        XEiJ.mpuClockTime += XEiJ.busWaitTime.rtc;
  3507:        XEiJ.busSuper (MemoryMappedDevice.MMD_RTC_NEXT, 0x00e8a000, 0x00e8c000);  //RTC RTC
  3508:        RP5C15.rtcUpdate ();
  3509:        return RP5C15.rtcReadByte (a + 1);
  3510:      }
  3511:     @Override protected int mmdRwz (int a) throws M68kException {
  3512:        XEiJ.mpuClockTime += XEiJ.busWaitTime.rtc;
  3513:        XEiJ.busSuper (MemoryMappedDevice.MMD_RTC_NEXT, 0x00e8a000, 0x00e8c000);  //RTC RTC
  3514:        RP5C15.rtcUpdate ();
  3515:        return RP5C15.rtcReadByte (a + 1);
  3516:      }
  3517:     @Override protected int mmdRls (int a) throws M68kException {
  3518:        XEiJ.mpuClockTime += XEiJ.busWaitTime.rtc * 2;
  3519:        XEiJ.busSuper (MemoryMappedDevice.MMD_RTC_NEXT, 0x00e8a000, 0x00e8c000);  //RTC RTC
  3520:        RP5C15.rtcUpdate ();
  3521:        return (RP5C15.rtcReadByte (a + 1) << 16 |
  3522:                RP5C15.rtcReadByte (a + 3));
  3523:      }
  3524:     //ライト
  3525:     @Override protected void mmdWb (int a, int d) throws M68kException {
  3526:        if ((a & 1) == 0 &&  //偶数アドレスのバイトライト
  3527:            !XEiJ.currentIsSecond) {  //Xellent30の030モードではない
  3528:          super.mmdWb (a, d);  //バスエラー
  3529:        }
  3530:        XEiJ.mpuClockTime += XEiJ.busWaitTime.rtc;
  3531:        XEiJ.busSuper (MemoryMappedDevice.MMD_RTC_NEXT, 0x00e8a000, 0x00e8c000);  //RTC RTC
  3532:        RP5C15.rtcUpdate ();
  3533:        RP5C15.rtcWriteByte (a, d);
  3534:      }
  3535:     @Override protected void mmdWw (int a, int d) throws M68kException {
  3536:        XEiJ.mpuClockTime += XEiJ.busWaitTime.rtc;
  3537:        XEiJ.busSuper (MemoryMappedDevice.MMD_RTC_NEXT, 0x00e8a000, 0x00e8c000);  //RTC RTC
  3538:        RP5C15.rtcUpdate ();
  3539:        RP5C15.rtcWriteByte (a + 1, d);
  3540:      }
  3541:     @Override protected void mmdWl (int a, int d) throws M68kException {
  3542:        XEiJ.mpuClockTime += XEiJ.busWaitTime.rtc * 2;
  3543:        XEiJ.busSuper (MemoryMappedDevice.MMD_RTC_NEXT, 0x00e8a000, 0x00e8c000);  //RTC RTC
  3544:        RP5C15.rtcUpdate ();
  3545:        RP5C15.rtcWriteByte (a + 1, d >> 16);
  3546:        RP5C15.rtcWriteByte (a + 3, d);
  3547:      }
  3548:   },  //MMD_RTC_FIRST
  3549: 
  3550:   //--------------------------------------------------------------------------------
  3551:   //MMD_RTC_NEXT RTC
  3552:   MMD_RTC_NEXT {
  3553:     @Override public String toString () {
  3554:       return Multilingual.mlnJapanese ? "RTC" : "RTC";  //Real-Time Clock
  3555:     }
  3556:     //ピーク
  3557:     @Override protected byte mmdPbs (int a) {
  3558:       return (byte) RP5C15.rtcPeekByte (a);
  3559:     }
  3560:     @Override protected int mmdPbz (int a) {
  3561:       return RP5C15.rtcPeekByte (a);
  3562:     }
  3563:     @Override protected int mmdPws (int a) {
  3564:       return RP5C15.rtcPeekByte (a + 1);
  3565:     }
  3566:     @Override protected int mmdPwz (int a) {
  3567:       return RP5C15.rtcPeekByte (a + 1);
  3568:     }
  3569:     @Override protected int mmdPls (int a) {
  3570:       return (RP5C15.rtcPeekByte (a + 1) << 16 |
  3571:               RP5C15.rtcPeekByte (a + 3));
  3572:     }
  3573:     //リード
  3574:     @Override protected byte mmdRbs (int a) throws M68kException {
  3575:        if ((a & 1) == 0 &&  //偶数アドレスのバイトリード
  3576:            !XEiJ.currentIsSecond) {  //Xellent30の030モードではない
  3577:          return super.mmdRbs (a);  //バスエラー
  3578:        }
  3579:        XEiJ.mpuClockTime += XEiJ.busWaitTime.rtc;
  3580:        return (byte) RP5C15.rtcReadByte (a);
  3581:      }
  3582:     @Override protected int mmdRbz (int a) throws M68kException {
  3583:        if ((a & 1) == 0 &&  //偶数アドレスのバイトリード
  3584:            !XEiJ.currentIsSecond) {  //Xellent30の030モードではない
  3585:          return super.mmdRbz (a);  //バスエラー
  3586:        }
  3587:        XEiJ.mpuClockTime += XEiJ.busWaitTime.rtc;
  3588:        return RP5C15.rtcReadByte (a);
  3589:      }
  3590:     @Override protected int mmdRws (int a) throws M68kException {
  3591:        XEiJ.mpuClockTime += XEiJ.busWaitTime.rtc;
  3592:        return RP5C15.rtcReadByte (a + 1);
  3593:      }
  3594:     @Override protected int mmdRwz (int a) throws M68kException {
  3595:        XEiJ.mpuClockTime += XEiJ.busWaitTime.rtc;
  3596:        return RP5C15.rtcReadByte (a + 1);
  3597:      }
  3598:     @Override protected int mmdRls (int a) throws M68kException {
  3599:        XEiJ.mpuClockTime += XEiJ.busWaitTime.rtc * 2;
  3600:        return (RP5C15.rtcReadByte (a + 1) << 16 |
  3601:                RP5C15.rtcReadByte (a + 3));
  3602:      }
  3603:     //ライト
  3604:     @Override protected void mmdWb (int a, int d) throws M68kException {
  3605:        if ((a & 1) == 0 &&  //偶数アドレスのバイトライト
  3606:            !XEiJ.currentIsSecond) {  //Xellent30の030モードではない
  3607:          super.mmdWb (a, d);  //バスエラー
  3608:        }
  3609:        XEiJ.mpuClockTime += XEiJ.busWaitTime.rtc;
  3610:        RP5C15.rtcWriteByte (a, d);
  3611:      }
  3612:     @Override protected void mmdWw (int a, int d) throws M68kException {
  3613:        XEiJ.mpuClockTime += XEiJ.busWaitTime.rtc;
  3614:        RP5C15.rtcWriteByte (a + 1, d);
  3615:      }
  3616:     @Override protected void mmdWl (int a, int d) throws M68kException {
  3617:        XEiJ.mpuClockTime += XEiJ.busWaitTime.rtc * 2;
  3618:        RP5C15.rtcWriteByte (a + 1, d >> 16);
  3619:        RP5C15.rtcWriteByte (a + 3, d);
  3620:      }
  3621:   },  //MMD_RTC_NEXT
  3622: 
  3623:   //--------------------------------------------------------------------------------
  3624:   //MMD_RTC_TEST RTC
  3625:   MMD_RTC_TEST {
  3626:     @Override public String toString () {
  3627:       return Multilingual.mlnJapanese ? "RTC テスト" : "RTC test";  //Real-Time Clock
  3628:     }
  3629:     //ピーク
  3630:     @Override protected byte mmdPbs (int a) {
  3631:       return (byte) RP5C15.rtcPeekByte (a);
  3632:     }
  3633:     @Override protected int mmdPbz (int a) {
  3634:       return RP5C15.rtcPeekByte (a);
  3635:     }
  3636:     @Override protected int mmdPws (int a) {
  3637:       return RP5C15.rtcPeekByte (a + 1);
  3638:     }
  3639:     @Override protected int mmdPwz (int a) {
  3640:       return RP5C15.rtcPeekByte (a + 1);
  3641:     }
  3642:     @Override protected int mmdPls (int a) {
  3643:       return (RP5C15.rtcPeekByte (a + 1) << 16 |
  3644:               RP5C15.rtcPeekByte (a + 3));
  3645:     }
  3646:     //リード
  3647:     @Override protected byte mmdRbs (int a) throws M68kException {
  3648:        if ((a & 1) == 0 &&  //偶数アドレスのバイトリード
  3649:            !XEiJ.currentIsSecond) {  //Xellent30の030モードではない
  3650:          return super.mmdRbs (a);  //バスエラー
  3651:        }
  3652:        XEiJ.mpuClockTime += XEiJ.busWaitTime.rtc;
  3653:        RP5C15.rtcTestUpdate ();
  3654:        return (byte) RP5C15.rtcReadByte (a);
  3655:      }
  3656:     @Override protected int mmdRbz (int a) throws M68kException {
  3657:        if ((a & 1) == 0 &&  //偶数アドレスのバイトリード
  3658:            !XEiJ.currentIsSecond) {  //Xellent30の030モードではない
  3659:          return super.mmdRbz (a);  //バスエラー
  3660:        }
  3661:        XEiJ.mpuClockTime += XEiJ.busWaitTime.rtc;
  3662:        RP5C15.rtcTestUpdate ();
  3663:        return RP5C15.rtcReadByte (a);
  3664:      }
  3665:     @Override protected int mmdRws (int a) throws M68kException {
  3666:        XEiJ.mpuClockTime += XEiJ.busWaitTime.rtc;
  3667:        RP5C15.rtcTestUpdate ();
  3668:        return RP5C15.rtcReadByte (a + 1);
  3669:      }
  3670:     @Override protected int mmdRwz (int a) throws M68kException {
  3671:        XEiJ.mpuClockTime += XEiJ.busWaitTime.rtc;
  3672:        RP5C15.rtcTestUpdate ();
  3673:        return RP5C15.rtcReadByte (a + 1);
  3674:      }
  3675:     @Override protected int mmdRls (int a) throws M68kException {
  3676:        XEiJ.mpuClockTime += XEiJ.busWaitTime.rtc * 2;
  3677:        RP5C15.rtcTestUpdate ();
  3678:        return (RP5C15.rtcReadByte (a + 1) << 16 |
  3679:                RP5C15.rtcReadByte (a + 3));
  3680:      }
  3681:     //ライト
  3682:     @Override protected void mmdWb (int a, int d) throws M68kException {
  3683:        if ((a & 1) == 0 &&  //偶数アドレスのバイトライト
  3684:            !XEiJ.currentIsSecond) {  //Xellent30の030モードではない
  3685:          super.mmdWb (a, d);  //バスエラー
  3686:        }
  3687:        XEiJ.mpuClockTime += XEiJ.busWaitTime.rtc;
  3688:        RP5C15.rtcTestUpdate ();
  3689:        RP5C15.rtcWriteByte (a, d);
  3690:      }
  3691:     @Override protected void mmdWw (int a, int d) throws M68kException {
  3692:        XEiJ.mpuClockTime += XEiJ.busWaitTime.rtc;
  3693:        RP5C15.rtcTestUpdate ();
  3694:        RP5C15.rtcWriteByte (a + 1, d);
  3695:      }
  3696:     @Override protected void mmdWl (int a, int d) throws M68kException {
  3697:        XEiJ.mpuClockTime += XEiJ.busWaitTime.rtc * 2;
  3698:        RP5C15.rtcTestUpdate ();
  3699:        RP5C15.rtcWriteByte (a + 1, d >> 16);
  3700:        RP5C15.rtcWriteByte (a + 3, d);
  3701:      }
  3702:   },  //MMD_RTC_TEST
  3703: 
  3704:   //--------------------------------------------------------------------------------
  3705:   //MMD_PRN プリンタポート
  3706:   //
  3707:   //  $00E8C000~$00E8C003(偶数)  バイトリードは$FF。バイトライトは$??。ワードリードは$FFxx。ワードライトは$??xx
  3708:   //  $00E8C000~$00E8C003(奇数)  バイトリードは$FF。バイトライトは$??
  3709:   //  $00E8C004~$00E8DFFF  $00E8C000~$00E8C003の繰り返し(?)
  3710:   //
  3711:   MMD_PRN {
  3712:     @Override public String toString () {
  3713:       return Multilingual.mlnJapanese ? "プリンタポート" : "Printer Port";
  3714:     }
  3715:     //リード
  3716:     @Override protected int mmdRbz (int a) throws M68kException {
  3717:        XEiJ.mpuClockTime += XEiJ.busWaitTime.prnport;
  3718:        a &= 3;
  3719:        return (a == (PrinterPort.PRN_DATA & 3) ? PrinterPort.prnReadData () :
  3720:                a == (PrinterPort.PRN_STROBE & 3) ? PrinterPort.prnReadStrobe () :
  3721:                0xff);
  3722:      }
  3723:     @Override protected int mmdRwz (int a) throws M68kException {
  3724:        return 0xff00 | mmdRbz (a + 1);
  3725:      }
  3726:     @Override protected int mmdRls (int a) throws M68kException {
  3727:        return 0xff00ff00 | mmdRbz (a + 1) << 16 | mmdRbz (a + 3);
  3728:      }
  3729:     //ライト
  3730:     @Override protected void mmdWb (int a, int d) throws M68kException {
  3731:        XEiJ.mpuClockTime += XEiJ.busWaitTime.prnport;
  3732:        a &= 3;
  3733:        if (a == (PrinterPort.PRN_DATA & 3)) {
  3734:          PrinterPort.prnWriteData (d);
  3735:        } else if (a == (PrinterPort.PRN_STROBE & 3)) {
  3736:          PrinterPort.prnWriteStrobe (d);
  3737:        }
  3738:      }
  3739:     @Override protected void mmdWw (int a, int d) throws M68kException {
  3740:        mmdWb (a + 1, d);
  3741:      }
  3742:     @Override protected void mmdWl (int a, int d) throws M68kException {
  3743:        mmdWb (a + 1, d >> 16);
  3744:        mmdWb (a + 3, d);
  3745:      }
  3746:   },  //MMD_PRN
  3747: 
  3748:   //--------------------------------------------------------------------------------
  3749:   //MMD_SYS システムポート
  3750:   //
  3751:   //  $00E8E000~$00E8E00F(偶数)  バイトリードは$FF、バイトライトは$??、ワードリードは$FFxx、ワードライトは$??xx
  3752:   //  $00E8E000~$00E8E00F(奇数)  バイトリードは$xx、バイトライトは$xx
  3753:   //  $00E8E010~$00E8FFFF  $00E8E000~$00E8E00Fの繰り返し
  3754:   //
  3755:   MMD_SYS {
  3756:     @Override public String toString () {
  3757:       return Multilingual.mlnJapanese ? "システムポート" : "System Port";
  3758:     }
  3759:     //リード
  3760:     @Override protected int mmdRbz (int a) throws M68kException {
  3761:        XEiJ.mpuClockTime += XEiJ.busWaitTime.sysport;
  3762:        switch (a & 15) {
  3763:        case 0x01:
  3764:          return 0b11110000 | VideoController.vcnTargetContrastPort;
  3765:        case 0x03:
  3766:          return 0b11111000 | XEiJ.pnlStereoscopicShutter;
  3767:        case 0x07:
  3768:          return 0b11110100 | (Keyboard.kbdOn ? 8 : 0) | CRTC.crtHRLPort << 1;
  3769:        case 0x0b:
  3770:          return (XEiJ.currentModel.isX68030 () ? 0xdc :
  3771:                  XEiJ.currentMPU < Model.MPU_MC68020 ?
  3772:                  XEiJ.mpuClockMHz <= 10.0 ? 0xff : 0xfe :
  3773:                  XEiJ.mpuClockMHz <= 20.0 ? 0xff : 0xfe);
  3774:        }
  3775:        return 0xff;
  3776:      }
  3777:     @Override protected int mmdRwz (int a) throws M68kException {
  3778:        return 0xff00 | mmdRbz (a + 1);
  3779:      }
  3780:     @Override protected int mmdRls (int a) throws M68kException {
  3781:        return 0xff00ff00 | mmdRbz (a + 1) << 16 | mmdRbz (a + 3);
  3782:      }
  3783:     //ライト
  3784:     @Override protected void mmdWb (int a, int d) throws M68kException {
  3785:        d &= 0xff;
  3786:        switch (a & 15) {
  3787:        case 0x01:
  3788:          VideoController.vcnTargetContrastPort = d & 15;
  3789:          {
  3790:            int curr = VideoController.vcnTargetContrastMask == 0 ? VideoController.vcnTargetContrastPort : VideoController.vcnTargetContrastTest;
  3791:            if (VideoController.vcnTargetContrastCurr != curr) {
  3792:              VideoController.vcnTargetContrastCurr = curr;
  3793:              VideoController.vcnTargetScaledContrast = VideoController.VCN_CONTRAST_SCALE * VideoController.vcnTargetContrastCurr;
  3794:              CRTC.crtContrastClock = XEiJ.mpuClockTime;
  3795:              CRTC.crtFrameTaskClock = Math.min (CRTC.crtContrastClock, CRTC.crtCaptureClock);
  3796:            }
  3797:          }
  3798:          return;
  3799:        case 0x03:
  3800:          XEiJ.pnlStereoscopicShutter = d & 3;
  3801:          break;
  3802:        case 0x07:
  3803:          {
  3804:            CRTC.crtHRLPort = d >> 1 & 1;
  3805:            int curr = CRTC.crtHRLMask == 0 ? CRTC.crtHRLPort : CRTC.crtHRLTest;
  3806:            if (CRTC.crtHRLCurr != curr) {
  3807:              CRTC.crtHRLCurr = curr;
  3808:              CRTC.crtRestart ();
  3809:            }
  3810:            if ((d & 1 << 2) != 0) {
  3811:              XEiJ.sysResetNMI ();  //NMIリセット
  3812:            }
  3813:          }
  3814:          return;
  3815:        case 0x09:
  3816:          if (XEiJ.currentModel.isX68030 ()) {
  3817:            //X68030のとき
  3818:            //  d=ROMウェイト設定値<<4|RAMウェイト設定値
  3819:            //  ROMウェイト
  3820:            //    ROMウェイト設定値+2
  3821:            //  RAMウェイト
  3822:            //    RAMウェイト設定値が0のとき
  3823:            //      スタティックカラムが有効なとき0
  3824:            //      スタティックカラムが無効なとき4
  3825:            //    RAMウェイト設定値が0でないとき
  3826:            //      RAMウェイト設定値+2
  3827:            //  ROMとRAMにはキャッシュが効く
  3828:            if (XEiJ.currentModel.isX68030 ()) {  //X68030
  3829:              XEiJ.mpuROMWaitCycles = (d >> 4 & 15) + 2;
  3830:              XEiJ.mpuRAMWaitCycles = (d & 15) == 0 ? 0 : (d & 15) + 2;
  3831:              XEiJ.mpuSetWait ();
  3832:            }
  3833:          }
  3834:          return;
  3835:        case 0x0d:
  3836:          SRAM.smrWriteEnableOn = d == 0x31;
  3837:          return;
  3838:        }
  3839:      }
  3840:     @Override protected void mmdWw (int a, int d) throws M68kException {
  3841:        mmdWb (a + 1, d);
  3842:      }
  3843:     @Override protected void mmdWl (int a, int d) throws M68kException {
  3844:        mmdWb (a + 1, d >> 16);
  3845:        mmdWb (a + 3, d);
  3846:      }
  3847:   },  //MMD_SYS
  3848: 
  3849:   //--------------------------------------------------------------------------------
  3850:   //MMD_OPM FM音源
  3851:   //
  3852:   //  $00E90000  バイトリードはバスエラー、バイトライトはバスエラー、ワードリードは$FFFF、ワードライトは$??xx
  3853:   //  $00E90001  バイトリードは$FF、バイトライトは$xx
  3854:   //  $00E90002  バイトリードはバスエラー、バイトライトはバスエラー、ワードリードは$FFxx、ワードライトは$??xx
  3855:   //  $00E90003  バイトリードは$xx、バイトライトは$xx
  3856:   //  $00E90004~$00E91FFF  $00E90000~$00E90003の繰り返し
  3857:   //
  3858:   MMD_OPM {
  3859:     @Override public String toString () {
  3860:       return Multilingual.mlnJapanese ? "FM 音源" : "FM Sound Generator";
  3861:     }
  3862:     //リード
  3863:     @Override protected int mmdRbz (int a) throws M68kException {
  3864:        if ((a & 1) == 0 &&  //偶数アドレスのバイトリード
  3865:            !XEiJ.currentIsSecond) {  //Xellent30の030モードではない
  3866:          return super.mmdRbz (a);  //バスエラー
  3867:        }
  3868:        XEiJ.mpuClockTime += XEiJ.busWaitTime.opm;
  3869:        return (a & 3) == 3 ? OPM.opmYM2151.readStatus () : 0xff;
  3870:      }
  3871:     @Override protected int mmdRwz (int a) throws M68kException {
  3872:        return 0xff00 | mmdRbz (a + 1);
  3873:      }
  3874:     @Override protected int mmdRls (int a) throws M68kException {
  3875:        return 0xff00ff00 | mmdRbz (a + 1) << 16 | mmdRbz (a + 3);
  3876:      }
  3877:     //ライト
  3878:     @Override protected void mmdWb (int a, int d) throws M68kException {
  3879:        if ((a & 1) == 0 &&  //偶数アドレスのバイトライト
  3880:            !XEiJ.currentIsSecond) {  //Xellent30の030モードではない
  3881:          super.mmdWb (a, d);  //バスエラー
  3882:        }
  3883:        XEiJ.mpuClockTime += XEiJ.busWaitTime.opm;
  3884:        a &= XEiJ.BUS_MOTHER_MASK;
  3885:        a &= 3;
  3886:        d &= 0xff;
  3887:        if (a == 3) {  //データレジスタ
  3888:          OPM.opmYM2151.generate (SoundSource.SND_CHANNELS *
  3889:                                  (OPM.OPM_BLOCK_SAMPLES - Math.max (0, (int) ((double) (SoundSource.sndBlockClock - XEiJ.mpuClockTime) /
  3890:                                                                               (double) OPM.OPM_SAMPLE_TIME))));
  3891:          OPM.opmYM2151.writeData (d);
  3892:        } else if (a == 1) {  //アドレスレジスタ
  3893:          OPM.opmYM2151.writeAddress (d);
  3894:        }
  3895:      }
  3896:     @Override protected void mmdWw (int a, int d) throws M68kException {
  3897:        mmdWb (a + 1, d);
  3898:      }
  3899:     @Override protected void mmdWl (int a, int d) throws M68kException {
  3900:        mmdWb (a + 1, d >> 16);
  3901:        mmdWb (a + 3, d);
  3902:      }
  3903:   },  //MMD_OPM
  3904: 
  3905:   //--------------------------------------------------------------------------------
  3906:   //MMD_PCM ADPCM音源
  3907:   //
  3908:   //  $00E92000~$00E92003(偶数)  バイトリードはバスエラー、バイトライトはバスエラー、ワードリードは$FFxx、ワードライトは$??xx
  3909:   //  $00E92000~$00E92003(奇数)  バイトリードは$xx、バイトライトは$xx
  3910:   //  $00E92004~$00E93FFF  $00E92000~$00E92003の繰り返し
  3911:   //
  3912:   MMD_PCM {
  3913:     @Override public String toString () {
  3914:       return Multilingual.mlnJapanese ? "ADPCM 音源" : "ADPCM Sound Generator";
  3915:     }
  3916:     //リード
  3917:     @Override protected int mmdRbz (int a) throws M68kException {
  3918:        if ((a & 1) == 0 &&  //偶数アドレスのバイトリード
  3919:            !XEiJ.currentIsSecond) {  //Xellent30の030モードではない
  3920:          return super.mmdRbz (a);  //バスエラー
  3921:        }
  3922:        XEiJ.mpuClockTime += XEiJ.busWaitTime.adpcm;
  3923:        return (a & 3) == 1 ? (ADPCM.pcmActive ? 0b10000000 : 0) | 0x40 : 0xff;
  3924:      }
  3925:     @Override protected int mmdRwz (int a) throws M68kException {
  3926:        return 0xff00 | mmdRbz (a + 1);
  3927:      }
  3928:     @Override protected int mmdRls (int a) throws M68kException {
  3929:        return 0xff00ff00 | mmdRbz (a + 1) << 16 | mmdRbz (a + 3);
  3930:      }
  3931:     //ライト
  3932:     @Override protected void mmdWb (int a, int d) throws M68kException {
  3933:        if ((a & 1) == 0 &&  //偶数アドレスのバイトライト
  3934:            !XEiJ.currentIsSecond) {  //Xellent30の030モードではない
  3935:          super.mmdWb (a, d);  //バスエラー
  3936:        }
  3937:        XEiJ.mpuClockTime += XEiJ.busWaitTime.adpcm;
  3938:        a &= XEiJ.BUS_MOTHER_MASK;
  3939:        a &= 3;
  3940:        if (a == 1) {  //コマンド
  3941:          if ((d & 0b00000001) != 0) {  //動作終了
  3942:            if (ADPCM.pcmActive) {  //動作中
  3943:              ADPCM.pcmClock = XEiJ.FAR_FUTURE;
  3944:              TickerQueue.tkqRemove (SoundSource.sndPcmTicker);
  3945:              ADPCM.pcmActive = false;
  3946:              ADPCM.pcmEncodedData = -1;
  3947:              ADPCM.pcmDecoderPointer = 0;
  3948:              HD63450.dmaRisePCL (3);
  3949:            }
  3950:          } else if ((d & 0b00000010) != 0) {  //動作開始
  3951:            if (!ADPCM.pcmActive) {  //停止中
  3952:              //現在のブロックの残り時間が1サンプルの時間の倍数になるように切り上げる
  3953:              int remainingSamples = Math.max (0, (int) ((double) (SoundSource.sndBlockClock - XEiJ.mpuClockTime) / (double) ADPCM.PCM_SAMPLE_TIME));  //現在のブロックの残りサンプル数
  3954:              ADPCM.pcmClock = SoundSource.sndBlockClock - ADPCM.PCM_SAMPLE_TIME * (long) remainingSamples;  //書き込み開始時刻
  3955:              TickerQueue.tkqAdd (SoundSource.sndPcmTicker, ADPCM.pcmClock);
  3956:              ADPCM.pcmActive = true;
  3957:              int newPointer = SoundSource.SND_CHANNELS * (ADPCM.PCM_BLOCK_SAMPLES - remainingSamples);  //書き込み開始位置
  3958:              if (ADPCM.pcmPointer < newPointer) {
  3959:                ADPCM.pcmFillBuffer (newPointer);
  3960:              } else {
  3961:                ADPCM.pcmPointer = newPointer;  //少し戻る場合がある
  3962:              }
  3963:              //DMAに最初のデータを要求する
  3964:              HD63450.dmaFallPCL (3);
  3965:            }
  3966:            //} else if ((d & 0b00000100) != 0) {  //録音開始
  3967:            //! 非対応
  3968:          }
  3969:        } else if (a == 3) {  //データ
  3970:          if (ADPCM.pcmActive) {
  3971:            ADPCM.pcmEncodedData = d & 0xff;
  3972:            HD63450.dmaRisePCL (3);
  3973:          }
  3974:        }
  3975:      }
  3976:     @Override protected void mmdWw (int a, int d) throws M68kException {
  3977:        mmdWb (a + 1, d);
  3978:      }
  3979:     @Override protected void mmdWl (int a, int d) throws M68kException {
  3980:        mmdWb (a + 1, d >> 16);
  3981:        mmdWb (a + 3, d);
  3982:      }
  3983:   },  //MMD_PCM
  3984: 
  3985:   //--------------------------------------------------------------------------------
  3986:   //MMD_FDC FDコントローラ
  3987:   //
  3988:   //  $00E94000~$00E94007(偶数)  バイトリードはバスエラー、バイトライトはバスエラー、ワードリードは$FFxx、ワードライトは$??xx
  3989:   //  $00E94000~$00E94007(奇数)  バイトリードは$xx、バイトライトは$xx
  3990:   //  $00E94008~$00E95FFF  $00E94000~$00E94007の繰り返し
  3991:   //
  3992:   MMD_FDC {
  3993:     @Override public String toString () {
  3994:       return Multilingual.mlnJapanese ? "FD コントローラ" : "FD Controller";
  3995:     }
  3996:     //ピーク
  3997:     @Override protected byte mmdPbs (int a) {
  3998:       return (byte) mmdPbz (a);
  3999:     }
  4000:     @Override protected int mmdPbz (int a) {
  4001:       a &= XEiJ.BUS_MOTHER_MASK;
  4002:       switch (a) {
  4003:       case FDC.FDC_STATUS_PORT:  //0x00e94001
  4004:         return FDC.fdcPeekStatus ();
  4005:       case FDC.FDC_DATA_PORT:  //0x00e94003
  4006:         return FDC.fdcPeekData ();
  4007:       case FDC.FDC_DRIVE_STATUS:  //0x00e94005
  4008:         return FDC.fdcPeekDriveStatus ();
  4009:       }
  4010:       return 0xff;
  4011:     }
  4012:     @Override protected int mmdPws (int a) {
  4013:       return (short) (mmdPbz (a) << 8 | mmdPbz (a + 1));
  4014:     }
  4015:     @Override protected int mmdPwz (int a) {
  4016:       return mmdPbz (a) << 8 | mmdPbz (a + 1);
  4017:     }
  4018:     @Override protected int mmdPls (int a) {
  4019:       return mmdPwz (a) << 16 | mmdPwz (a + 2);
  4020:     }
  4021:     //リード
  4022:     @Override protected int mmdRbz (int a) throws M68kException {
  4023:        if ((a & 1) == 0 &&  //偶数アドレスのバイトリード
  4024:            !XEiJ.currentIsSecond) {  //Xellent30の030モードではない
  4025:          return super.mmdRbz (a);  //バスエラー
  4026:        }
  4027:        XEiJ.mpuClockTime += XEiJ.busWaitTime.fdc;
  4028:        a &= XEiJ.BUS_MOTHER_MASK;
  4029:        switch (a) {
  4030:        case FDC.FDC_STATUS_PORT:  //0x00e94001
  4031:          return FDC.fdcReadStatus ();
  4032:        case FDC.FDC_DATA_PORT:  //0x00e94003
  4033:          return FDC.fdcReadData ();
  4034:        case FDC.FDC_DRIVE_STATUS:  //0x00e94005
  4035:          return FDC.fdcReadDriveStatus ();
  4036:        }
  4037:        return 0xff;
  4038:      }
  4039:     @Override protected int mmdRwz (int a) throws M68kException {
  4040:        return 0xff00 | mmdRbz (a + 1);
  4041:      }
  4042:     @Override protected int mmdRls (int a) throws M68kException {
  4043:        return 0xff00ff00 | mmdRbz (a + 1) << 16 | mmdRbz (a + 3);
  4044:      }
  4045:     //ライト
  4046:     @Override protected void mmdWb (int a, int d) throws M68kException {
  4047:        if ((a & 1) == 0 &&  //偶数アドレスのバイトライト
  4048:            !XEiJ.currentIsSecond) {  //Xellent30の030モードではない
  4049:          super.mmdWb (a, d);  //バスエラー
  4050:        }
  4051:        XEiJ.mpuClockTime += XEiJ.busWaitTime.fdc;
  4052:        a &= XEiJ.BUS_MOTHER_MASK;
  4053:        switch (a) {
  4054:        case FDC.FDC_STATUS_PORT:  //0x00e94001
  4055:          FDC.fdcWriteCommand (d);
  4056:          break;
  4057:        case FDC.FDC_DATA_PORT:  //0x00e94003
  4058:          FDC.fdcWriteData (d);
  4059:          break;
  4060:        case FDC.FDC_DRIVE_STATUS:  //0x00e94005
  4061:          FDC.fdcWriteDriveControl (d);
  4062:          break;
  4063:        case FDC.FDC_DRIVE_SELECT:  //0x00e94007
  4064:          FDC.fdcWriteDriveSelect (d);
  4065:          break;
  4066:        }
  4067:      }
  4068:     @Override protected void mmdWw (int a, int d) throws M68kException {
  4069:        mmdWb (a + 1, d);
  4070:      }
  4071:     @Override protected void mmdWl (int a, int d) throws M68kException {
  4072:        mmdWb (a + 1, d >> 16);
  4073:        mmdWb (a + 3, d);
  4074:      }
  4075:   },  //MMD_FDC
  4076: 
  4077:   //--------------------------------------------------------------------------------
  4078:   //MMD_HDC SASI HDコントローラ
  4079:   //
  4080:   //  $00E96000~$00E9603F(偶数)  バイトリードはバスエラー、バイトライトはバスエラー、ワードリードは$FFxx、ワードライトは$??xx
  4081:   //  $00E96000~$00E9603F(奇数)  バイトリードは$xx、バイトライトは$xx
  4082:   //                              X68030の$00E96000~$00E9601Fは$00,$00,$FF,$FFの繰り返し。$00E9603Fは$FF
  4083:   //  $00E96040~$00E97FFF  $00E96000~$00E9603Fの繰り返し
  4084:   //
  4085:   MMD_HDC {
  4086:     @Override public String toString () {
  4087:       return Multilingual.mlnJapanese ? "内蔵 SASI/SCSI ポート" : "Internal SASI/SCSI Port";  //SCSIのIはInterfaceなのだからSCSIインタフェイスはおかしい
  4088:     }
  4089:     //ピーク
  4090:     @Override protected int mmdPbz (int a) {
  4091:       a &= XEiJ.BUS_MOTHER_MASK;
  4092:       if ((a & 0x01) == 0) {  //偶数番地
  4093:         return 0xff;
  4094:       } else {  //奇数番地
  4095:         if (SPC.spcSCSIINOn) {  //SCSI内蔵機
  4096:           if ((a & 0x20) == 0) {  //SASIポート
  4097:             return ((a & 0x02) == 0 ? 0x00 : 0xff);
  4098:           } else {  //SCSIポート
  4099:             return SPC.spcSCSIINChip.spiPeek (a);
  4100:           }
  4101:         } else {  //SASI内蔵機
  4102:           switch (a & 0x3f) {
  4103:           case HDC.HDC_DATA_PORT & 0x3f:  //0x00e96001
  4104:             return HDC.hdcPeekData ();
  4105:           case HDC.HDC_STATUS_PORT & 0x3f:  //0x00e96003
  4106:             return HDC.hdcPeekStatus ();
  4107:           case HDC.HDC_RESET_PORT & 0x3f:  //0x00e96005
  4108:             return 0xff;
  4109:           case HDC.HDC_SELECTION_PORT & 0x3f:  //0x00e96007
  4110:             return 0xff;
  4111:           default:
  4112:             return 0xff;
  4113:           }
  4114:         }
  4115:       }
  4116:     }
  4117:     @Override protected int mmdPwz (int a) {
  4118:       a &= XEiJ.BUS_MOTHER_MASK;
  4119:       return 0xff00 | mmdPbz (a + 1);
  4120:     }
  4121:     @Override protected int mmdPls (int a) {
  4122:       a &= XEiJ.BUS_MOTHER_MASK;
  4123:       return 0xff00ff00 | mmdPbz (a + 1) << 16 | mmdPbz (a + 3);
  4124:     }
  4125:     //リード
  4126:     @Override protected int mmdRbz (int a) throws M68kException {
  4127:        if ((a & 1) == 0 &&  //偶数アドレスのバイトリード
  4128:            !XEiJ.currentIsSecond) {  //Xellent30の030モードではない
  4129:          return super.mmdRbz (a);  //バスエラー
  4130:        }
  4131:        XEiJ.mpuClockTime += XEiJ.busWaitTime.hdc;
  4132:        a &= XEiJ.BUS_MOTHER_MASK;
  4133:        if ((a & 0x01) == 0) {  //偶数番地
  4134:          return super.mmdRbz (a);  //バスエラー
  4135:        } else {  //奇数番地
  4136:          if (SPC.spcSCSIINOn) {  //SCSI内蔵機
  4137:            if ((a & 0x20) == 0) {  //SASIポート
  4138:              return ((a & 0x02) == 0 ? 0x00 : 0xff);
  4139:            } else {  //SCSIポート
  4140:              return SPC.spcSCSIINChip.spiRead (a);
  4141:            }
  4142:          } else {  //SASI内蔵機
  4143:            switch (a & 0x3f) {
  4144:            case HDC.HDC_DATA_PORT & 0x3f:  //0x00e96001
  4145:              return HDC.hdcReadData ();
  4146:            case HDC.HDC_STATUS_PORT & 0x3f:  //0x00e96003
  4147:              return HDC.hdcReadStatus ();
  4148:            case HDC.HDC_RESET_PORT & 0x3f:  //0x00e96005
  4149:              return 0xff;
  4150:            case HDC.HDC_SELECTION_PORT & 0x3f:  //0x00e96007
  4151:              return 0xff;
  4152:            default:
  4153:              return 0xff;
  4154:            }
  4155:          }
  4156:        }
  4157:      }
  4158:     @Override protected int mmdRwz (int a) throws M68kException {
  4159:        return 0xff00 | mmdRbz (a + 1);
  4160:      }
  4161:     @Override protected int mmdRls (int a) throws M68kException {
  4162:        return 0xff00ff00 | mmdRbz (a + 1) << 16 | mmdRbz (a + 3);
  4163:      }
  4164:     //ライト
  4165:     @Override protected void mmdWb (int a, int d) throws M68kException {
  4166:        if ((a & 1) == 0 &&  //偶数アドレスのバイトライト
  4167:            !XEiJ.currentIsSecond) {  //Xellent30の030モードではない
  4168:          super.mmdWb (a, d);  //バスエラー
  4169:        }
  4170:        XEiJ.mpuClockTime += XEiJ.busWaitTime.hdc;
  4171:        a &= XEiJ.BUS_MOTHER_MASK;
  4172:        if ((a & 0x01) == 0) {  //偶数番地
  4173:          super.mmdWb (a, d);  //バスエラー
  4174:        } else {  //奇数番地
  4175:          if (SPC.spcSCSIINOn) {  //SCSI内蔵機
  4176:            if ((a & 0x20) == 0) {  //SASIポート
  4177:              return;
  4178:            } else {  //SCSIポート
  4179:              SPC.spcSCSIINChip.spiWrite (a, d);
  4180:              return;
  4181:            }
  4182:          } else {  //SASI内蔵機
  4183:            switch (a & 0x3f) {
  4184:            case HDC.HDC_DATA_PORT & 0x3f:  //0x00e96001
  4185:              HDC.hdcWriteData (d);
  4186:              return;
  4187:            case HDC.HDC_STATUS_PORT & 0x3f:  //0x00e96003
  4188:              HDC.hdcWriteCommand (d);
  4189:              return;
  4190:            case HDC.HDC_RESET_PORT & 0x3f:  //0x00e96005
  4191:              HDC.hdcWriteReset (d);
  4192:              return;
  4193:            case HDC.HDC_SELECTION_PORT & 0x3f:  //0x00e96007
  4194:              HDC.hdcWriteSelect (d);
  4195:              return;
  4196:            default:
  4197:              return;
  4198:            }
  4199:          }
  4200:        }
  4201:      }
  4202:     @Override protected void mmdWw (int a, int d) throws M68kException {
  4203:        mmdWb (a + 1, d);
  4204:      }
  4205:     @Override protected void mmdWl (int a, int d) throws M68kException {
  4206:        mmdWb (a + 1, d >> 16);
  4207:        mmdWb (a + 3, d);
  4208:      }
  4209:   },  //MMD_HDC
  4210: 
  4211:   //--------------------------------------------------------------------------------
  4212:   //MMD_SCC SCC
  4213:   //
  4214:   //  $00E98000~$00E98007(偶数)  バイトリードはバスエラー、バイトライトはバスエラー、ワードリードは$FFxx、ワードライトは$??xx
  4215:   //  $00E98000~$00E98007(奇数)  バイトリードは$xx、バイトライトは$xx
  4216:   //  $00E98008~$00E99FFF  $00E98000~$00E98007の繰り返し
  4217:   //
  4218:   MMD_SCC {
  4219:     @Override public String toString () {
  4220:       return Multilingual.mlnJapanese ? "SCC" : "SCC";  //Serial Communication Controller
  4221:     }
  4222:     //ピーク
  4223:     @Override protected int mmdPbz (int a) {
  4224:       return Z8530.sccReadByte (a, true);
  4225:     }
  4226:     @Override protected int mmdPwz (int a) {
  4227:       return 0xff00 | mmdPbz (a + 1);
  4228:     }
  4229:     @Override protected int mmdPls (int a) {
  4230:       return 0xff00ff00 | mmdPbz (a + 1) << 16 | mmdPbz (a + 3);
  4231:     }
  4232:     //リード
  4233:     @Override protected int mmdRbz (int a) throws M68kException {
  4234:        if ((a & 1) == 0 &&  //偶数アドレスのバイトリード
  4235:            !XEiJ.currentIsSecond) {  //Xellent30の030モードではない
  4236:          return super.mmdRbz (a);  //バスエラー
  4237:        }
  4238:        return Z8530.sccReadByte (a, false);
  4239:      }
  4240:     @Override protected int mmdRwz (int a) throws M68kException {
  4241:        return 0xff00 | mmdRbz (a + 1);
  4242:      }
  4243:     @Override protected int mmdRls (int a) throws M68kException {
  4244:        return 0xff00ff00 | mmdRbz (a + 1) << 16 | mmdRbz (a + 3);
  4245:      }
  4246:     //ライト
  4247:     @Override protected void mmdWb (int a, int d) throws M68kException {
  4248:        if ((a & 1) == 0 &&  //偶数アドレスのバイトライト
  4249:            !XEiJ.currentIsSecond) {  //Xellent30の030モードではない
  4250:          super.mmdWb (a, d);  //バスエラー
  4251:        }
  4252:        Z8530.sccWriteByte (a, d);
  4253:      }
  4254:     @Override protected void mmdWw (int a, int d) throws M68kException {
  4255:        mmdWb (a + 1, d);
  4256:      }
  4257:     @Override protected void mmdWl (int a, int d) throws M68kException {
  4258:        mmdWb (a + 1, d >> 16);
  4259:        mmdWb (a + 3, d);
  4260:      }
  4261:   },  //MMD_SCC
  4262: 
  4263:   //--------------------------------------------------------------------------------
  4264:   //MMD_PPI PPI
  4265:   //
  4266:   //  $00E9A000~$00E9A007(偶数)  バイトリードはバスエラー、バイトライトはバスエラー、ワードリードは$FFxx、ワードライトは$??xx
  4267:   //  $00E9A000~$00E9A007(奇数)  バイトリードは$xx、バイトライトは$xx
  4268:   //  $00E9A008~$00E9BFFF  $00E9A000~$00E9A007の繰り返し
  4269:   //
  4270:   MMD_PPI {
  4271:     @Override public String toString () {
  4272:       return Multilingual.mlnJapanese ? "PPI" : "PPI";  //Programmable Peripheral Interface
  4273:     }
  4274:     //リード
  4275:     @Override protected int mmdRbz (int a) throws M68kException {
  4276:        if ((a & 1) == 0 &&  //偶数アドレスのバイトリード
  4277:            !XEiJ.currentIsSecond) {  //Xellent30の030モードではない
  4278:          return super.mmdRbz (a);  //バスエラー
  4279:        }
  4280:        XEiJ.mpuClockTime += XEiJ.busWaitTime.ppi;
  4281:        return PPI.ppiReadByte (a);
  4282:      }
  4283:     @Override protected int mmdRwz (int a) throws M68kException {
  4284:        return 0xff00 | mmdRbz (a + 1);
  4285:      }
  4286:     @Override protected int mmdRls (int a) throws M68kException {
  4287:        return 0xff00ff00 | mmdRbz (a + 1) << 16 | mmdRbz (a + 3);
  4288:      }
  4289:     //ライト
  4290:     @Override protected void mmdWb (int a, int d) throws M68kException {
  4291:        if ((a & 1) == 0 &&  //偶数アドレスのバイトライト
  4292:            !XEiJ.currentIsSecond) {  //Xellent30の030モードではない
  4293:          super.mmdWb (a, d);  //バスエラー
  4294:        }
  4295:        XEiJ.mpuClockTime += XEiJ.busWaitTime.ppi;
  4296:        PPI.ppiWriteByte (a, d);
  4297:      }
  4298:     @Override protected void mmdWw (int a, int d) throws M68kException {
  4299:        mmdWb (a + 1, d);
  4300:      }
  4301:     @Override protected void mmdWl (int a, int d) throws M68kException {
  4302:        mmdWb (a + 1, d >> 16);
  4303:        mmdWb (a + 3, d);
  4304:      }
  4305:   },  //MMD_PPI
  4306: 
  4307:   //--------------------------------------------------------------------------------
  4308:   //MMD_IOI I/O割り込み
  4309:   //
  4310:   //  $00E9C000~$00E9C00F(偶数)  バイトリードはバスエラー、バイトライトはバスエラー、ワードリードは$FFxx、ワードライトは$??xx
  4311:   //  $00E9C000~$00E9C00F(奇数)  バイトリードは$xx、バイトライトは$xx
  4312:   //  $00E9C010~$00E9BFFF  $00E9C000~$00E9C00Fの繰り返し
  4313:   //
  4314:   MMD_IOI {
  4315:     @Override public String toString () {
  4316:       return Multilingual.mlnJapanese ? "I/O 割り込み" : "I/O Interrupt";
  4317:     }
  4318:     //リード
  4319:     @Override protected int mmdRbz (int a) throws M68kException {
  4320:        if ((a & 1) == 0 &&  //偶数アドレスのバイトリード
  4321:            !XEiJ.currentIsSecond) {  //Xellent30の030モードではない
  4322:          return super.mmdRbz (a);  //バスエラー
  4323:        }
  4324:        XEiJ.mpuClockTime += XEiJ.busWaitTime.ioi;
  4325:        a &= XEiJ.BUS_MOTHER_MASK;
  4326:        if (a == IOInterrupt.IOI_STATUS) {
  4327:          return IOInterrupt.ioiReadStatus ();
  4328:        } else if (a == IOInterrupt.IOI_VECTOR) {  //ライトオンリー。リードすると$FFが返る
  4329:          //return IOInterrupt.ioiReadVector ();
  4330:          return 0xff;
  4331:        } else {
  4332:          return super.mmdRbz (a);  //バスエラー
  4333:        }
  4334:      }
  4335:     @Override protected int mmdRwz (int a) throws M68kException {
  4336:        return 0xff00 | mmdRbz (a + 1);
  4337:      }
  4338:     @Override protected int mmdRls (int a) throws M68kException {
  4339:        return 0xff00ff00 | mmdRbz (a + 1) << 16 | mmdRbz (a + 3);
  4340:      }
  4341:     //ライト
  4342:     @Override protected void mmdWb (int a, int d) throws M68kException {
  4343:        if ((a & 1) == 0 &&  //偶数アドレスのバイトライト
  4344:            !XEiJ.currentIsSecond) {  //Xellent30の030モードではない
  4345:          super.mmdWb (a, d);  //バスエラー
  4346:        }
  4347:        XEiJ.mpuClockTime += XEiJ.busWaitTime.ioi;
  4348:        a &= XEiJ.BUS_MOTHER_MASK;
  4349:        if (a == IOInterrupt.IOI_STATUS) {
  4350:          IOInterrupt.ioiWriteEnable (d);
  4351:        } else if (a == IOInterrupt.IOI_VECTOR) {
  4352:          IOInterrupt.ioiWriteVector (d);
  4353:        } else {
  4354:          super.mmdWb (a, d);  //バスエラー
  4355:        }
  4356:      }
  4357:     @Override protected void mmdWw (int a, int d) throws M68kException {
  4358:        mmdWb (a + 1, d);
  4359:      }
  4360:     @Override protected void mmdWl (int a, int d) throws M68kException {
  4361:        mmdWb (a + 1, d >> 16);
  4362:        mmdWb (a + 3, d);
  4363:      }
  4364:   },  //MMD_IOI
  4365: 
  4366:   //--------------------------------------------------------------------------------
  4367:   //MMD_XB1 拡張ボード領域1
  4368:   MMD_XB1 {
  4369:     @Override public String toString () {
  4370:       return Multilingual.mlnJapanese ? "拡張ボード領域 1" : "Expansion Board Area 1";
  4371:     }
  4372:     //ピーク
  4373:     @Override protected int mmdPbz (int a) {
  4374:       if ((a & (XEiJ.BUS_MOTHER_MASK & -0x20)) == 0x00e9e000) {  //数値演算プロセッサボード1
  4375:         return XEiJ.fpuCoproboard1.cirPeekByteZero (a);
  4376:       }
  4377:       if ((a & (XEiJ.BUS_MOTHER_MASK & -0x20)) == 0x00e9e080) {  //数値演算プロセッサボード2
  4378:         return XEiJ.fpuCoproboard2.cirPeekByteZero (a);
  4379:       }
  4380:       if ((a & (XEiJ.BUS_MOTHER_MASK & -HFS.HFS_ROM_SIZE)) == HFS.HFS_ADDRESS) {  //ホストファイルシステムインタフェイス
  4381:         a &= XEiJ.BUS_MOTHER_MASK;
  4382:         return MainMemory.mmrM8[a] & 0xff;
  4383:       }
  4384:       if (Keyboard.KBD_ZKEY_ON &&
  4385:           (a & (XEiJ.BUS_MOTHER_MASK & -Keyboard.KBD_ZKEY_IO_SIZE)) == Keyboard.KBD_ZKEY_IO_ADDRESS) {  //Zキーボード
  4386:         return Keyboard.kbdZKeyIOReadByte (a);
  4387:       }
  4388:       return 0xff;
  4389:     }
  4390:     @Override protected int mmdPwz (int a) {
  4391:       if ((a & (XEiJ.BUS_MOTHER_MASK & -0x20)) == 0x00e9e000) {  //数値演算プロセッサボード1
  4392:         return XEiJ.fpuCoproboard1.cirPeekWordZero (a);
  4393:       }
  4394:       if ((a & (XEiJ.BUS_MOTHER_MASK & -0x20)) == 0x00e9e080) {  //数値演算プロセッサボード2
  4395:         return XEiJ.fpuCoproboard2.cirPeekWordZero (a);
  4396:       }
  4397:       if ((a & (XEiJ.BUS_MOTHER_MASK & -HFS.HFS_ROM_SIZE)) == HFS.HFS_ADDRESS) {  //ホストファイルシステムインタフェイス
  4398:         a &= XEiJ.BUS_MOTHER_MASK;
  4399:         return (char) (MainMemory.mmrM8[a] << 8 | (MainMemory.mmrM8[a + 1] & 0xff));
  4400:       }
  4401:       if (Keyboard.KBD_ZKEY_ON &&
  4402:           (a & (XEiJ.BUS_MOTHER_MASK & -Keyboard.KBD_ZKEY_IO_SIZE)) == Keyboard.KBD_ZKEY_IO_ADDRESS) {  //Zキーボード
  4403:         return Keyboard.kbdZKeyIOReadWord (a);
  4404:       }
  4405:       return 0xffff;
  4406:     }
  4407:     @Override protected int mmdPls (int a) {
  4408:       if ((a & (XEiJ.BUS_MOTHER_MASK & -0x20)) == 0x00e9e000) {  //数値演算プロセッサボード1
  4409:         return XEiJ.fpuCoproboard1.cirPeekLong (a);
  4410:       }
  4411:       if ((a & (XEiJ.BUS_MOTHER_MASK & -0x20)) == 0x00e9e080) {  //数値演算プロセッサボード2
  4412:         return XEiJ.fpuCoproboard2.cirPeekLong (a);
  4413:       }
  4414:       if ((a & (XEiJ.BUS_MOTHER_MASK & -HFS.HFS_ROM_SIZE)) == HFS.HFS_ADDRESS) {  //ホストファイルシステムインタフェイス
  4415:         a &= XEiJ.BUS_MOTHER_MASK;
  4416:         return MainMemory.mmrM8[a] << 24 | (MainMemory.mmrM8[a + 1] & 0xff) << 16 | (char) (MainMemory.mmrM8[a + 2] << 8 | (MainMemory.mmrM8[a + 3] & 0xff));
  4417:       }
  4418:       if (Keyboard.KBD_ZKEY_ON &&
  4419:           (a & (XEiJ.BUS_MOTHER_MASK & -Keyboard.KBD_ZKEY_IO_SIZE)) == Keyboard.KBD_ZKEY_IO_ADDRESS) {  //Zキーボード
  4420:         return Keyboard.kbdZKeyIOReadLong (a);
  4421:       }
  4422:       return -1;
  4423:     }
  4424:     //リード
  4425:     @Override protected int mmdRbz (int a) throws M68kException {
  4426:        if ((a & (XEiJ.BUS_MOTHER_MASK & -0x20)) == 0x00e9e000) {  //数値演算プロセッサボード1
  4427:          return XEiJ.fpuCoproboard1.cirReadByteZero (a);
  4428:        }
  4429:        if ((a & (XEiJ.BUS_MOTHER_MASK & -0x20)) == 0x00e9e080) {  //数値演算プロセッサボード2
  4430:          return XEiJ.fpuCoproboard2.cirReadByteZero (a);
  4431:        }
  4432:        if ((a & (XEiJ.BUS_MOTHER_MASK & -HFS.HFS_ROM_SIZE)) == HFS.HFS_ADDRESS) {  //ホストファイルシステムインタフェイス
  4433:          a &= XEiJ.BUS_MOTHER_MASK;
  4434:          return MainMemory.mmrM8[a] & 0xff;
  4435:        }
  4436:        if (Keyboard.KBD_ZKEY_ON &&
  4437:            (a & (XEiJ.BUS_MOTHER_MASK & -Keyboard.KBD_ZKEY_IO_SIZE)) == Keyboard.KBD_ZKEY_IO_ADDRESS) {  //Zキーボード
  4438:          return Keyboard.kbdZKeyIOReadByte (a);
  4439:        }
  4440:        return super.mmdRbz (a);  //バスエラー
  4441:      }
  4442:     @Override protected int mmdRwz (int a) throws M68kException {
  4443:        if ((a & (XEiJ.BUS_MOTHER_MASK & -0x20)) == 0x00e9e000) {  //数値演算プロセッサボード1
  4444:          return XEiJ.fpuCoproboard1.cirReadWordZero (a);
  4445:        }
  4446:        if ((a & (XEiJ.BUS_MOTHER_MASK & -0x20)) == 0x00e9e080) {  //数値演算プロセッサボード2
  4447:          return XEiJ.fpuCoproboard2.cirReadWordZero (a);
  4448:        }
  4449:        if ((a & (XEiJ.BUS_MOTHER_MASK & -HFS.HFS_ROM_SIZE)) == HFS.HFS_ADDRESS) {  //ホストファイルシステムインタフェイス
  4450:          a &= XEiJ.BUS_MOTHER_MASK;
  4451:          return (char) (MainMemory.mmrM8[a] << 8 | (MainMemory.mmrM8[a + 1] & 0xff));
  4452:        }
  4453:        if (Keyboard.KBD_ZKEY_ON &&
  4454:            (a & (XEiJ.BUS_MOTHER_MASK & -Keyboard.KBD_ZKEY_IO_SIZE)) == Keyboard.KBD_ZKEY_IO_ADDRESS) {  //Zキーボード
  4455:          return Keyboard.kbdZKeyIOReadWord (a);
  4456:        }
  4457:        return super.mmdRwz (a);  //バスエラー
  4458:      }
  4459:     @Override protected int mmdRls (int a) throws M68kException {
  4460:        if ((a & (XEiJ.BUS_MOTHER_MASK & -0x20)) == 0x00e9e000) {  //数値演算プロセッサボード1
  4461:          return XEiJ.fpuCoproboard1.cirReadLong (a);
  4462:        }
  4463:        if ((a & (XEiJ.BUS_MOTHER_MASK & -0x20)) == 0x00e9e080) {  //数値演算プロセッサボード2
  4464:          return XEiJ.fpuCoproboard2.cirReadLong (a);
  4465:        }
  4466:        if ((a & (XEiJ.BUS_MOTHER_MASK & -HFS.HFS_ROM_SIZE)) == HFS.HFS_ADDRESS) {  //ホストファイルシステムインタフェイス
  4467:          a &= XEiJ.BUS_MOTHER_MASK;
  4468:          return MainMemory.mmrM8[a] << 24 | (MainMemory.mmrM8[a + 1] & 0xff) << 16 | (char) (MainMemory.mmrM8[a + 2] << 8 | (MainMemory.mmrM8[a + 3] & 0xff));
  4469:        }
  4470:        if (Keyboard.KBD_ZKEY_ON &&
  4471:            (a & (XEiJ.BUS_MOTHER_MASK & -Keyboard.KBD_ZKEY_IO_SIZE)) == Keyboard.KBD_ZKEY_IO_ADDRESS) {  //Zキーボード
  4472:          return Keyboard.kbdZKeyIOReadLong (a);
  4473:        }
  4474:        return super.mmdRls (a);  //バスエラー
  4475:      }
  4476:     //ライト
  4477:     @Override protected void mmdWb (int a, int d) throws M68kException {
  4478:        if ((a & (XEiJ.BUS_MOTHER_MASK & -0x20)) == 0x00e9e000) {  //数値演算プロセッサボード1
  4479:          XEiJ.fpuCoproboard1.cirWriteByte (a, d);
  4480:          return;
  4481:        }
  4482:        if ((a & (XEiJ.BUS_MOTHER_MASK & -0x20)) == 0x00e9e080) {  //数値演算プロセッサボード2
  4483:          XEiJ.fpuCoproboard2.cirWriteByte (a, d);
  4484:          return;
  4485:        }
  4486:        if (Keyboard.KBD_ZKEY_ON &&
  4487:            (a & (XEiJ.BUS_MOTHER_MASK & -Keyboard.KBD_ZKEY_IO_SIZE)) == Keyboard.KBD_ZKEY_IO_ADDRESS) {  //Zキーボード
  4488:          Keyboard.kbdZKeyIOWriteByte (a, d);
  4489:          return;
  4490:        }
  4491:        super.mmdWb (a, d);  //バスエラー
  4492:      }
  4493:     @Override protected void mmdWw (int a, int d) throws M68kException {
  4494:        if ((a & (XEiJ.BUS_MOTHER_MASK & -0x20)) == 0x00e9e000) {  //数値演算プロセッサボード1
  4495:          XEiJ.fpuCoproboard1.cirWriteWord (a, d);
  4496:          return;
  4497:        }
  4498:        if ((a & (XEiJ.BUS_MOTHER_MASK & -0x20)) == 0x00e9e080) {  //数値演算プロセッサボード2
  4499:          XEiJ.fpuCoproboard2.cirWriteWord (a, d);
  4500:          return;
  4501:        }
  4502:        if (Keyboard.KBD_ZKEY_ON &&
  4503:            (a & (XEiJ.BUS_MOTHER_MASK & -Keyboard.KBD_ZKEY_IO_SIZE)) == Keyboard.KBD_ZKEY_IO_ADDRESS) {  //Zキーボード
  4504:          Keyboard.kbdZKeyIOWriteWord (a, d);
  4505:          return;
  4506:        }
  4507:        super.mmdWw (a, d);  //バスエラー
  4508:      }
  4509:     @Override protected void mmdWl (int a, int d) throws M68kException {
  4510:        if ((a & (XEiJ.BUS_MOTHER_MASK & -0x20)) == 0x00e9e000) {  //数値演算プロセッサボード1
  4511:          XEiJ.fpuCoproboard1.cirWriteLong (a, d);
  4512:          return;
  4513:        }
  4514:        if ((a & (XEiJ.BUS_MOTHER_MASK & -0x20)) == 0x00e9e080) {  //数値演算プロセッサボード2
  4515:          XEiJ.fpuCoproboard2.cirWriteLong (a, d);
  4516:          return;
  4517:        }
  4518:        if (Keyboard.KBD_ZKEY_ON &&
  4519:            (a & (XEiJ.BUS_MOTHER_MASK & -Keyboard.KBD_ZKEY_IO_SIZE)) == Keyboard.KBD_ZKEY_IO_ADDRESS) {  //Zキーボード
  4520:          Keyboard.kbdZKeyIOWriteLong (a, d);
  4521:          return;
  4522:        }
  4523:        super.mmdWl (a, d);  //バスエラー
  4524:      }
  4525:   },  //MMD_XB1
  4526: 
  4527:   //--------------------------------------------------------------------------------
  4528:   //MMD_EXS 拡張SCSI
  4529:   //  必要なときだけ接続される
  4530:   //  拡張SCSIのROMのサイズは8KBなのでリードのときのバスエラーのチェックは不要
  4531:   //  ライトのときはROMには書き込めないのでSPCのレジスタでなければバスエラー
  4532:   MMD_EXS {
  4533:     @Override public String toString () {
  4534:       return Multilingual.mlnJapanese ? "拡張 SCSI ポート" : "Expansion SCSI Port";
  4535:     }
  4536:     //ピーク
  4537:     @Override protected byte mmdPbs (int a) {
  4538:       a &= XEiJ.BUS_MOTHER_MASK;
  4539:        return (a & -32) == SPC.SPC_BASE_EX ? (byte) SPC.spcSCSIEXChip.spiPeek (a) : MainMemory.mmrM8[a];
  4540:      }
  4541:     @Override protected int mmdPbz (int a) {
  4542:       a &= XEiJ.BUS_MOTHER_MASK;
  4543:        return (a & -32) == SPC.SPC_BASE_EX ? SPC.spcSCSIEXChip.spiPeek (a) : MainMemory.mmrM8[a] & 0xff;
  4544:      }
  4545:     @Override protected int mmdPws (int a) {
  4546:       a &= XEiJ.BUS_MOTHER_MASK;
  4547:        return mmdPbs (a) << 8 | mmdPbz (a + 1);
  4548:      }
  4549:     @Override protected int mmdPwz (int a) {
  4550:       a &= XEiJ.BUS_MOTHER_MASK;
  4551:        return mmdPbz (a) << 8 | mmdPbz (a + 1);
  4552:      }
  4553:     @Override protected int mmdPls (int a) {
  4554:       a &= XEiJ.BUS_MOTHER_MASK;
  4555:        return mmdPbs (a) << 24 | mmdPbz (a + 1) << 16 | mmdPbz (a + 2) << 8 | mmdPbz (a + 3);
  4556:      }
  4557:     //リード
  4558:     @Override protected byte mmdRbs (int a) throws M68kException {
  4559:        a &= XEiJ.BUS_MOTHER_MASK;
  4560:        return (a & -32) == SPC.SPC_BASE_EX ? (byte) SPC.spcSCSIEXChip.spiRead (a) : MainMemory.mmrM8[a];
  4561:      }
  4562:     @Override protected int mmdRbz (int a) throws M68kException {
  4563:        a &= XEiJ.BUS_MOTHER_MASK;
  4564:        return (a & -32) == SPC.SPC_BASE_EX ? SPC.spcSCSIEXChip.spiRead (a) : MainMemory.mmrM8[a] & 0xff;
  4565:      }
  4566:     @Override protected int mmdRws (int a) throws M68kException {
  4567:        a &= XEiJ.BUS_MOTHER_MASK;
  4568:        return mmdRbs (a) << 8 | mmdRbz (a + 1);
  4569:      }
  4570:     @Override protected int mmdRwz (int a) throws M68kException {
  4571:        a &= XEiJ.BUS_MOTHER_MASK;
  4572:        return mmdRbz (a) << 8 | mmdRbz (a + 1);
  4573:      }
  4574:     @Override protected int mmdRls (int a) throws M68kException {
  4575:        a &= XEiJ.BUS_MOTHER_MASK;
  4576:        return mmdRbs (a) << 24 | mmdRbz (a + 1) << 16 | mmdRbz (a + 2) << 8 | mmdRbz (a + 3);
  4577:      }
  4578:     //ライト
  4579:     @Override protected void mmdWb (int a, int d) throws M68kException {
  4580:        a &= XEiJ.BUS_MOTHER_MASK;
  4581:        if ((a & -32) == SPC.SPC_BASE_EX) {
  4582:          SPC.spcSCSIEXChip.spiWrite (a, d);
  4583:          return;
  4584:        }
  4585:        super.mmdWb (a, d);  //バスエラー
  4586:      }
  4587:     @Override protected void mmdWw (int a, int d) throws M68kException {
  4588:        a &= XEiJ.BUS_MOTHER_MASK;
  4589:        mmdWb (a    , d >> 8);
  4590:        mmdWb (a + 1, d     );
  4591:      }
  4592:     @Override protected void mmdWl (int a, int d) throws M68kException {
  4593:        a &= XEiJ.BUS_MOTHER_MASK;
  4594:        mmdWw (a    , d >> 16);
  4595:        mmdWw (a + 2, d      );
  4596:      }
  4597:   },  //MMD_EXS
  4598: 
  4599:   //--------------------------------------------------------------------------------
  4600:   //MMD_XB2 拡張ボード領域2
  4601:   //
  4602:   //  $00EAFF80  リードはバスエラー、バイトライトはバスエラー、ワードライトは$00200000~$003FFFFFがあるとき$??xx、ないときバスエラー
  4603:   //  $00EAFF81  リードはバスエラー、ライトは$00200000~$003FFFFFがあるとき$xx、ないときバスエラー
  4604:   //  $00EAFF82  リードはバスエラー、バイトライトはバスエラー、ワードライトは$00400000~$005FFFFFがあるとき$??xx、ないときバスエラー
  4605:   //  $00EAFF83  リードはバスエラー、ライトは$00400000~$005FFFFFがあるとき$xx、ないときバスエラー
  4606:   //  $00EAFF84  リードはバスエラー、バイトライトはバスエラー、ワードライトは$00600000~$007FFFFFがあるとき$??xx、ないときバスエラー
  4607:   //  $00EAFF85  リードはバスエラー、ライトは$00600000~$007FFFFFがあるとき$xx、ないときバスエラー
  4608:   //  $00EAFF86  リードはバスエラー、バイトライトはバスエラー、ワードライトは$00800000~$009FFFFFがあるとき$??xx、ないときバスエラー
  4609:   //  $00EAFF87  リードはバスエラー、ライトは$00800000~$009FFFFFがあるとき$xx、ないときバスエラー
  4610:   //  $00EAFF88  リードはバスエラー、バイトライトはバスエラー、ワードライトは$00A00000~$00BFFFFFがあるとき$??xx、ないときバスエラー
  4611:   //  $00EAFF89  リードはバスエラー、ライトは$00A00000~$00BFFFFFがあるとき$xx、ないときバスエラー
  4612:   //  $00EAFF8A~$00EAFF8F  バスエラー
  4613:   //  $00EAFF90~$00EAFFFF  $00EAFF80~$00EAFF8Fの繰り返し
  4614:   //
  4615:   //  拡張
  4616:   //  $00EAFF7F  バンクメモリのページ番号
  4617:   //
  4618:   MMD_XB2 {
  4619:     @Override public String toString () {
  4620:       return Multilingual.mlnJapanese ? "拡張ボード領域 2" : "Expansion Board Area 2";
  4621:     }
  4622:     //リード
  4623:     @Override protected int mmdRbz (int a) throws M68kException {
  4624:        a &= XEiJ.BUS_MOTHER_MASK;
  4625:        if (0x00eaff81 <= a && a <= 0x00eaff89 && (a & 1) != 0) {  //スーパーバイザエリア設定ポート
  4626:          return MainMemory.mmrM8[a] & 0xff;  //読み出せるようにしておく(本来はライトオンリー)
  4627:        }
  4628:        if (XEiJ.bnkOn && a == 0x00eaff7f) {  //バンクメモリのページ番号
  4629:          return XEiJ.bnkPageStart >> 17;
  4630:        }
  4631:        return super.mmdRbz (a);  //バスエラー
  4632:      }
  4633:     //ライト
  4634:     @Override protected void mmdWb (int a, int d) throws M68kException {
  4635:        a &= XEiJ.BUS_MOTHER_MASK;
  4636:        if (0x00eaff81 <= a && a <= 0x00eaff89 && (a & 1) != 0) {  //スーパーバイザエリア設定ポート
  4637:          MainMemory.mmrM8[a] = (byte) d;  //読み出せるようにしておく(本来はライトオンリー)
  4638:          a = (a & 14) + 2 << 20;  //1,3,5,7,9→2,4,6,8,a
  4639:          for (int m = 1; m <= 128; m <<= 1) {
  4640:            if ((d & m) == 0) {  //ユーザエリア
  4641:              XEiJ.busUser ( MemoryMappedDevice.MMD_MMR, a, a + 0x00040000);
  4642:            } else {  //スーパーバイザエリア
  4643:              XEiJ.busSuper (MemoryMappedDevice.MMD_MMR, a, a + 0x00040000);
  4644:            }
  4645:            a += 0x00040000;
  4646:          }
  4647:          return;
  4648:        }
  4649:        if (XEiJ.bnkOn && a == 0x00eaff7f) {  //バンクメモリのページ番号
  4650:          XEiJ.bnkPageStart = (d & 0xff) << 17;
  4651:          return;
  4652:        }
  4653:        super.mmdWb (a, d);  //バスエラー
  4654:      }
  4655:   },  //MMD_XB2
  4656: 
  4657:   //--------------------------------------------------------------------------------
  4658:   //MMD_SPR スプライト画面
  4659:   //
  4660:   //  CRTCのR20の下位5ビットが%1??1?でないとき
  4661:   //    $00EB0000-$00EB03FF  スプライトスクロールレジスタ(0~127)
  4662:   //    $00EB0400-$00EB07FF  $FF。256枚表示のときスプライトスクロールレジスタ(128~255)
  4663:   //    $00EB0800-$00EB0811  設定
  4664:   //    $00EB0812-$00EB7FFF  $FF
  4665:   //    $00EB8000-$00EBFFFF  スプライトPCG・テキストエリア
  4666:   //
  4667:   //  CRTCのR20の下位5ビットが%1??1?のとき
  4668:   //    $00EB0000-$00EB03FF  バスエラー
  4669:   //    $00EB0400-$00EB07FF  バスエラー
  4670:   //    $00EB0800-$00EB0811  設定
  4671:   //    $00EB0812-$00EB7FFF  $FF
  4672:   //    $00EB8000-$00EBFFFF  バスエラー
  4673:   //
  4674:   //  メモ
  4675:   //    スプライトPCG・テキストエリアにバイトサイズで書き込むとデータが破壊される
  4676:   //
  4677:   MMD_SPR {
  4678:     @Override public String toString () {
  4679:       return Multilingual.mlnJapanese ? "スプライト画面" : "Sprite Screen";
  4680:     }
  4681:     //リード
  4682:     @Override protected byte mmdRbs (int a) throws M68kException {
  4683:        a &= XEiJ.BUS_MOTHER_MASK;
  4684:        return (a & 1) == 0 ? (byte) (mmdRwz (a) >> 8) : (byte) mmdRwz (a - 1);
  4685:      }
  4686:     @Override protected int mmdRbz (int a) throws M68kException {
  4687:        a &= XEiJ.BUS_MOTHER_MASK;
  4688:        return (a & 1) == 0 ? mmdRwz (a) >> 8 : mmdRwz (a - 1) & 0xff;
  4689:      }
  4690:     @Override protected int mmdRws (int a) throws M68kException {
  4691:        a &= XEiJ.BUS_MOTHER_MASK;
  4692:        return (short) mmdRwz (a);
  4693:      }
  4694:     @Override protected int mmdRwz (int a) throws M68kException {
  4695:        XEiJ.mpuClockTime += XEiJ.busWaitTime.sprc;
  4696:        a &= XEiJ.BUS_MOTHER_MASK;
  4697:        if (a < 0x00eb0800) {  //スプライトスクロールレジスタ
  4698:          if (!SpriteScreen.sprAccessible) {
  4699:            return super.mmdRwz (a);  //バスエラー
  4700:          }
  4701:          int n = (a >> 3) & 0xff;  //スプライト番号
  4702:          if (SpriteScreen.sprNumberOfSprites <= n) {
  4703:            return 0xffff;
  4704:          }
  4705:          switch (a & 0x06) {
  4706:          case 0:  //x座標
  4707:            return SpriteScreen.sprX[n];
  4708:          case 2:  //y座標
  4709:            return SpriteScreen.sprY[n];
  4710:          case 4:  //パターン番号、パレットブロック、水平反転、垂直反転
  4711:            return (SpriteScreen.sprV[n] ? 0x8000 : 0) | (SpriteScreen.sprH[n] ? 0x4000 : 0) | SpriteScreen.sprColPort[n] << 4 | SpriteScreen.sprNum[n];
  4712:          case 6:  //プライオリティ
  4713:            return SpriteScreen.sprPrw[n];
  4714:          }
  4715:        } else if (a < 0x00eb8000) {  //各種レジスタ
  4716:          switch (a) {
  4717:          case SpriteScreen.SPR_REG0_BG0_X:
  4718:            return SpriteScreen.sprReg0Bg0XPort;
  4719:          case SpriteScreen.SPR_REG1_BG0_Y:
  4720:            return SpriteScreen.sprReg1Bg0YPort;
  4721:          case SpriteScreen.SPR_REG2_BG1_X:
  4722:            return SpriteScreen.sprReg2Bg1XPort;
  4723:          case SpriteScreen.SPR_REG3_BG1_Y:
  4724:            return SpriteScreen.sprReg3Bg1YPort;
  4725:          case SpriteScreen.SPR_REG4_BG_CTRL:
  4726:            return SpriteScreen.sprReg4BgCtrlPort;
  4727:          case SpriteScreen.SPR_REG5_H_FRONT_END:
  4728:            return SpriteScreen.sprReg5HFrontEndPort;
  4729:          case SpriteScreen.SPR_REG6_H_BACK_END:
  4730:            return SpriteScreen.sprReg6HBackEndPort;
  4731:          case SpriteScreen.SPR_REG7_V_BACK_END:
  4732:            return SpriteScreen.sprReg7VBackEndPort;
  4733:          case SpriteScreen.SPR_REG8_RESO:
  4734:            return SpriteScreen.sprReg8ResoPort;
  4735:          }
  4736:          return 0xffff;
  4737:        } else {  //PCGエリアとテキストエリア
  4738:          if (!SpriteScreen.sprAccessible) {
  4739:            return super.mmdRwz (a);  //バスエラー
  4740:          }
  4741:          int t = a >> 2 & 0x1fff;
  4742:          return (a & 0x02) == 0 ? SpriteScreen.sprPatPort[t] >>> 16 : (char) SpriteScreen.sprPatPort[t];
  4743:        }
  4744:        return 0;
  4745:      }
  4746:     @Override protected int mmdRls (int a) throws M68kException {
  4747:        a &= XEiJ.BUS_MOTHER_MASK;
  4748:        return mmdRwz (a) << 16 | mmdRwz (a + 2);
  4749:      }
  4750:     //ライト
  4751:     @Override protected void mmdWb (int a, int d) throws M68kException {
  4752:        a &= XEiJ.BUS_MOTHER_MASK;
  4753:        if (a < 0x00eb0800 || 0x00eb8000 <= a) {
  4754:          mmdWw (a & ~1, d << 8 | (d & 0xff));  //上位バイトと下位バイトに同じ値を書き込む
  4755:        } else {
  4756:          if ((a & 1) == 0) {
  4757:            mmdWw (a, d << 8 | (mmdRwz (a) & 0xff));
  4758:          } else {
  4759:            mmdWw (a - 1, (mmdRwz (a - 1) & ~0xff) | (d & 0xff));
  4760:          }
  4761:        }
  4762:      }
  4763:     @Override protected void mmdWw (int a, int d) throws M68kException {
  4764:        XEiJ.mpuClockTime += XEiJ.busWaitTime.sprc;
  4765:        a &= XEiJ.BUS_MOTHER_MASK;
  4766:        if (a < 0x00eb0800) {  //スプライトスクロールレジスタ
  4767:          if (!SpriteScreen.sprAccessible) {
  4768:            super.mmdWw (a, d);  //バスエラー
  4769:          }
  4770:          int n = (a >> 3) & 0xff;  //スプライト番号
  4771:          if (SpriteScreen.sprNumberOfSprites <= n) {
  4772:            return;
  4773:          }
  4774:          switch (a & 0x06) {
  4775:          case 0:  //x座標
  4776:            SpriteScreen.sprX[n] = (short) (d & 1023);
  4777:            break;
  4778:          case 2:  //y座標
  4779:            d &= 1023;
  4780:            if (SpriteScreen.sprY[n] != d) {
  4781:              int y = SpriteScreen.sprY[n];
  4782:              SpriteScreen.sprY[n] = (short) d;
  4783:              if (SpriteScreen.sprPrw[n] != 0) {
  4784:                int mask = ~(0x80000000 >>> n);  //intのシフトカウントは5bitでマスクされる
  4785:                int i = y << 3 | n >> 5;  //移動元
  4786:                SpriteScreen.sprRRmap[i            ] &= mask;
  4787:                SpriteScreen.sprRRmap[i + ( 1 << 3)] &= mask;
  4788:                SpriteScreen.sprRRmap[i + ( 2 << 3)] &= mask;
  4789:                SpriteScreen.sprRRmap[i + ( 3 << 3)] &= mask;
  4790:                SpriteScreen.sprRRmap[i + ( 4 << 3)] &= mask;
  4791:                SpriteScreen.sprRRmap[i + ( 5 << 3)] &= mask;
  4792:                SpriteScreen.sprRRmap[i + ( 6 << 3)] &= mask;
  4793:                SpriteScreen.sprRRmap[i + ( 7 << 3)] &= mask;
  4794:                SpriteScreen.sprRRmap[i + ( 8 << 3)] &= mask;
  4795:                SpriteScreen.sprRRmap[i + ( 9 << 3)] &= mask;
  4796:                SpriteScreen.sprRRmap[i + (10 << 3)] &= mask;
  4797:                SpriteScreen.sprRRmap[i + (11 << 3)] &= mask;
  4798:                SpriteScreen.sprRRmap[i + (12 << 3)] &= mask;
  4799:                SpriteScreen.sprRRmap[i + (13 << 3)] &= mask;
  4800:                SpriteScreen.sprRRmap[i + (14 << 3)] &= mask;
  4801:                SpriteScreen.sprRRmap[i + (15 << 3)] &= mask;
  4802:                mask = ~mask;
  4803:                i = d << 3 | n >> 5;  //移動先
  4804:                SpriteScreen.sprRRmap[i            ] |= mask;
  4805:                SpriteScreen.sprRRmap[i + ( 1 << 3)] |= mask;
  4806:                SpriteScreen.sprRRmap[i + ( 2 << 3)] |= mask;
  4807:                SpriteScreen.sprRRmap[i + ( 3 << 3)] |= mask;
  4808:                SpriteScreen.sprRRmap[i + ( 4 << 3)] |= mask;
  4809:                SpriteScreen.sprRRmap[i + ( 5 << 3)] |= mask;
  4810:                SpriteScreen.sprRRmap[i + ( 6 << 3)] |= mask;
  4811:                SpriteScreen.sprRRmap[i + ( 7 << 3)] |= mask;
  4812:                SpriteScreen.sprRRmap[i + ( 8 << 3)] |= mask;
  4813:                SpriteScreen.sprRRmap[i + ( 9 << 3)] |= mask;
  4814:                SpriteScreen.sprRRmap[i + (10 << 3)] |= mask;
  4815:                SpriteScreen.sprRRmap[i + (11 << 3)] |= mask;
  4816:                SpriteScreen.sprRRmap[i + (12 << 3)] |= mask;
  4817:                SpriteScreen.sprRRmap[i + (13 << 3)] |= mask;
  4818:                SpriteScreen.sprRRmap[i + (14 << 3)] |= mask;
  4819:                SpriteScreen.sprRRmap[i + (15 << 3)] |= mask;
  4820:              }
  4821:            }
  4822:            break;
  4823:          case 4:  //パターン番号、パレットブロック、水平反転、垂直反転
  4824:            {
  4825:              int num = SpriteScreen.sprNum[n];  //元のパターン番号
  4826:              SpriteScreen.sprNum[n] = (short) (d & 0xff);
  4827:              SpriteScreen.sprColPort[n] = (short) (d >> 4 & 0x0f << 4);
  4828:              SpriteScreen.sprH[n] = (short) (d << 1) < 0;
  4829:              SpriteScreen.sprV[n] = (short) d < 0;
  4830:              if (SpriteScreen.sprPrw[n] != 0) {
  4831:                int mask = 0x80000000 >>> n;  //intのシフトカウントは5bitでマスクされる
  4832:                SpriteScreen.sprPPmap[num << 3 | n >> 5] &= ~mask;  //消滅
  4833:                SpriteScreen.sprPPmap[(d & 0xff) << 3 | n >> 5] |= mask;  //出現
  4834:              }
  4835:            }
  4836:            break;
  4837:          case 6:  //プライオリティ
  4838:            d &= 0x0003;
  4839:            int prw = SpriteScreen.sprPrw[n];
  4840:            SpriteScreen.sprPrw[n] = (byte) d;
  4841:            if (prw != d) {
  4842:              if (prw == 0) {  //出現
  4843:                int y = SpriteScreen.sprY[n];
  4844:                int mask = 0x80000000 >>> n;  //intのシフトカウントは5bitでマスクされる
  4845:                int i = y << 3 | n >> 5;
  4846:                SpriteScreen.sprRRmap[i            ] |= mask;
  4847:                SpriteScreen.sprRRmap[i + ( 1 << 3)] |= mask;
  4848:                SpriteScreen.sprRRmap[i + ( 2 << 3)] |= mask;
  4849:                SpriteScreen.sprRRmap[i + ( 3 << 3)] |= mask;
  4850:                SpriteScreen.sprRRmap[i + ( 4 << 3)] |= mask;
  4851:                SpriteScreen.sprRRmap[i + ( 5 << 3)] |= mask;
  4852:                SpriteScreen.sprRRmap[i + ( 6 << 3)] |= mask;
  4853:                SpriteScreen.sprRRmap[i + ( 7 << 3)] |= mask;
  4854:                SpriteScreen.sprRRmap[i + ( 8 << 3)] |= mask;
  4855:                SpriteScreen.sprRRmap[i + ( 9 << 3)] |= mask;
  4856:                SpriteScreen.sprRRmap[i + (10 << 3)] |= mask;
  4857:                SpriteScreen.sprRRmap[i + (11 << 3)] |= mask;
  4858:                SpriteScreen.sprRRmap[i + (12 << 3)] |= mask;
  4859:                SpriteScreen.sprRRmap[i + (13 << 3)] |= mask;
  4860:                SpriteScreen.sprRRmap[i + (14 << 3)] |= mask;
  4861:                SpriteScreen.sprRRmap[i + (15 << 3)] |= mask;
  4862:                SpriteScreen.sprPPmap[SpriteScreen.sprNum[n] << 3 | n >> 5] |= mask;
  4863:              } else if (d == 0) {  //消滅
  4864:                int y = SpriteScreen.sprY[n];
  4865:                int mask = ~(0x80000000 >>> n);  //intのシフトカウントは5bitでマスクされる
  4866:                int i = y << 3 | n >> 5;
  4867:                SpriteScreen.sprRRmap[i            ] &= mask;
  4868:                SpriteScreen.sprRRmap[i + ( 1 << 3)] &= mask;
  4869:                SpriteScreen.sprRRmap[i + ( 2 << 3)] &= mask;
  4870:                SpriteScreen.sprRRmap[i + ( 3 << 3)] &= mask;
  4871:                SpriteScreen.sprRRmap[i + ( 4 << 3)] &= mask;
  4872:                SpriteScreen.sprRRmap[i + ( 5 << 3)] &= mask;
  4873:                SpriteScreen.sprRRmap[i + ( 6 << 3)] &= mask;
  4874:                SpriteScreen.sprRRmap[i + ( 7 << 3)] &= mask;
  4875:                SpriteScreen.sprRRmap[i + ( 8 << 3)] &= mask;
  4876:                SpriteScreen.sprRRmap[i + ( 9 << 3)] &= mask;
  4877:                SpriteScreen.sprRRmap[i + (10 << 3)] &= mask;
  4878:                SpriteScreen.sprRRmap[i + (11 << 3)] &= mask;
  4879:                SpriteScreen.sprRRmap[i + (12 << 3)] &= mask;
  4880:                SpriteScreen.sprRRmap[i + (13 << 3)] &= mask;
  4881:                SpriteScreen.sprRRmap[i + (14 << 3)] &= mask;
  4882:                SpriteScreen.sprRRmap[i + (15 << 3)] &= mask;
  4883:                SpriteScreen.sprPPmap[SpriteScreen.sprNum[n] << 3 | n >> 5] &= mask;
  4884:              }
  4885:            }
  4886:            break;
  4887:          }  //スプライトスクロールレジスタのswitch
  4888:          return;
  4889:        } else if (a < 0x00eb8000) {  //各種レジスタ
  4890:          switch (a) {
  4891:          case SpriteScreen.SPR_REG0_BG0_X:
  4892:            SpriteScreen.sprReg0Bg0XPort = d & 1023;
  4893:            {
  4894:              int curr = SpriteScreen.sprReg0Bg0XMask == 0 ? SpriteScreen.sprReg0Bg0XPort : SpriteScreen.sprReg0Bg0XTest;
  4895:              if (SpriteScreen.sprReg0Bg0XCurr != curr) {
  4896:                SpriteScreen.sprReg0Bg0XCurr = curr;
  4897:              }
  4898:            }
  4899:            return;
  4900:          case SpriteScreen.SPR_REG1_BG0_Y:
  4901:            SpriteScreen.sprReg1Bg0YPort = d & 1023;
  4902:            {
  4903:              int curr = SpriteScreen.sprReg1Bg0YMask == 0 ? SpriteScreen.sprReg1Bg0YPort : SpriteScreen.sprReg1Bg0YTest;
  4904:              if (SpriteScreen.sprReg1Bg0YCurr != curr) {
  4905:                SpriteScreen.sprReg1Bg0YCurr = curr;
  4906:              }
  4907:            }
  4908:            return;
  4909:          case SpriteScreen.SPR_REG2_BG1_X:
  4910:            SpriteScreen.sprReg2Bg1XPort = d & 1023;
  4911:            {
  4912:              int curr = SpriteScreen.sprReg2Bg1XMask == 0 ? SpriteScreen.sprReg2Bg1XPort : SpriteScreen.sprReg2Bg1XTest;
  4913:              if (SpriteScreen.sprReg2Bg1XCurr != curr) {
  4914:                SpriteScreen.sprReg2Bg1XCurr = curr;
  4915:              }
  4916:            }
  4917:            return;
  4918:          case SpriteScreen.SPR_REG3_BG1_Y:
  4919:            SpriteScreen.sprReg3Bg1YPort = d & 1023;
  4920:            {
  4921:              int curr = SpriteScreen.sprReg3Bg1YMask == 0 ? SpriteScreen.sprReg3Bg1YPort : SpriteScreen.sprReg3Bg1YTest;
  4922:              if (SpriteScreen.sprReg3Bg1YCurr != curr) {
  4923:                SpriteScreen.sprReg3Bg1YCurr = curr;
  4924:              }
  4925:            }
  4926:            return;
  4927:          case SpriteScreen.SPR_REG4_BG_CTRL:
  4928:            SpriteScreen.sprReg4BgCtrlPort = d & 2047;
  4929:            {
  4930:              int curr = SpriteScreen.sprReg4BgCtrlPort & ~SpriteScreen.sprReg4BgCtrlMask | SpriteScreen.sprReg4BgCtrlTest & SpriteScreen.sprReg4BgCtrlMask;
  4931:              if (SpriteScreen.sprReg4BgCtrlCurr != curr) {
  4932:                SpriteScreen.sprReg4BgCtrlCurr = curr;
  4933:              }
  4934:            }
  4935:            return;
  4936:          case SpriteScreen.SPR_REG5_H_FRONT_END:
  4937:            SpriteScreen.sprReg5HFrontEndPort = d & 0xff;
  4938:            {
  4939:              int curr = SpriteScreen.sprReg5HFrontEndMask == 0 ? SpriteScreen.sprReg5HFrontEndPort : SpriteScreen.sprReg5HFrontEndTest;
  4940:              if (SpriteScreen.sprReg5HFrontEndCurr != curr) {
  4941:                SpriteScreen.sprReg5HFrontEndCurr = curr;
  4942:              }
  4943:            }
  4944:            return;
  4945:          case SpriteScreen.SPR_REG6_H_BACK_END:
  4946:            SpriteScreen.sprReg6HBackEndPort = d & 63;
  4947:            {
  4948:              int curr = SpriteScreen.sprReg6HBackEndMask == 0 ? SpriteScreen.sprReg6HBackEndPort : SpriteScreen.sprReg6HBackEndTest;
  4949:              if (SpriteScreen.sprReg6HBackEndCurr != curr) {
  4950:                SpriteScreen.sprReg6HBackEndCurr = curr;
  4951:              }
  4952:            }
  4953:            return;
  4954:          case SpriteScreen.SPR_REG7_V_BACK_END:
  4955:            SpriteScreen.sprReg7VBackEndPort = d & 0xff;
  4956:            {
  4957:              int curr = SpriteScreen.sprReg7VBackEndMask == 0 ? SpriteScreen.sprReg7VBackEndPort : SpriteScreen.sprReg7VBackEndTest;
  4958:              if (SpriteScreen.sprReg7VBackEndCurr != curr) {
  4959:                SpriteScreen.sprReg7VBackEndCurr = curr;
  4960:              }
  4961:            }
  4962:            return;
  4963:          case SpriteScreen.SPR_REG8_RESO:
  4964:            SpriteScreen.sprReg8ResoPort = d & 31;
  4965:            {
  4966:              int curr = SpriteScreen.sprReg8ResoPort & ~SpriteScreen.sprReg8ResoMask | SpriteScreen.sprReg8ResoTest & SpriteScreen.sprReg8ResoMask;
  4967:              if (SpriteScreen.sprReg8ResoCurr != curr) {
  4968:                SpriteScreen.sprReg8ResoCurr = curr;
  4969:              }
  4970:            }
  4971:            return;
  4972:          }
  4973:          return;
  4974:        } else {  //PCGエリアとテキストエリア
  4975:          if (!SpriteScreen.sprAccessible) {
  4976:            super.mmdWw (a, d);  //バスエラー
  4977:          }
  4978:          if (0x00ebe000 <= a) {  //テキストエリア1
  4979:            int n = a >> 1 & 0x0fff;
  4980:            SpriteScreen.sprT1Num[n] = (short) ((d & 0xff) << 3);
  4981:            SpriteScreen.sprT1ColPort[n] = (short) ((d & 0x0f00) >> 4);
  4982:            SpriteScreen.sprT1H[n] = (short) (d << 1) < 0;
  4983:            SpriteScreen.sprT1V[n] = (short) d < 0;
  4984:          } else if (0x00ebc000 <= a) {  //テキストエリア0
  4985:            int n = a >> 1 & 0x0fff;
  4986:            SpriteScreen.sprT0Num[n] = (short) ((d & 0xff) << 3);
  4987:            SpriteScreen.sprT0ColPort[n] = (short) ((d & 0x0f00) >> 4);
  4988:            SpriteScreen.sprT0H[n] = (short) (d << 1) < 0;
  4989:            SpriteScreen.sprT0V[n] = (short) d < 0;
  4990:          }
  4991:          int t = a >> 2 & 0x1fff;
  4992:          SpriteScreen.sprPatPort[t] = (a & 0x02) == 0 ? d << 16 | (char) SpriteScreen.sprPatPort[t] : (SpriteScreen.sprPatPort[t] & ~0xffff) | (char) d;
  4993:        }  //PCGエリアとテキストエリア
  4994:      }  //mmdWw
  4995:     @Override protected void mmdWl (int a, int d) throws M68kException {
  4996:        a &= XEiJ.BUS_MOTHER_MASK;
  4997:        mmdWw (a    , d >> 16);
  4998:        mmdWw (a + 2, d      );
  4999:      }
  5000:   },  //MMD_SPR
  5001: 
  5002:   //--------------------------------------------------------------------------------
  5003:   //MMD_XB3 拡張ボード領域3
  5004:   //  $00EC0000~$00ECFFFF  64KB
  5005:   //  0x00ec0000  ユーザI/Oエリア
  5006:   //  0x00ec0000  Awesome
  5007:   //  0x00ec0000  Xellent30
  5008:   //  0x00ecc000  Mercury
  5009:   //  0x00ece000  Neptune
  5010:   //  0x00ecf000  Venus-X/030
  5011:   MMD_XB3 {
  5012:     @Override public String toString () {
  5013:       return Multilingual.mlnJapanese ? "拡張ボード領域 3" : "Expansion Board Area 3";
  5014:     }
  5015:     //リード
  5016:     @Override protected int mmdRbz (int a) throws M68kException {
  5017:        a &= XEiJ.BUS_MOTHER_MASK;
  5018:        if (XEiJ.currentAccelerator == XEiJ.ACCELERATOR_XELLENT30 &&
  5019:            XEiJ.xt3PortAddress <= a && a < XEiJ.xt3PortAddress + 0x4000) {  //Xellent30設定ポート
  5020:          return (a & 1) == 0 ? 0 : XEiJ.xt3PortRead ();
  5021:        }
  5022:        return super.mmdRbz (a);  //バスエラー
  5023:      }
  5024:     @Override protected int mmdRwz (int a) throws M68kException {
  5025:        a &= XEiJ.BUS_MOTHER_MASK;
  5026:        if (XEiJ.currentAccelerator == XEiJ.ACCELERATOR_XELLENT30 &&
  5027:            XEiJ.xt3PortAddress <= a && a < XEiJ.xt3PortAddress + 0x4000) {  //Xellent30設定ポート
  5028:          return XEiJ.xt3PortRead ();
  5029:        }
  5030:        return super.mmdRwz (a);  //バスエラー
  5031:      }
  5032:     @Override protected int mmdRls (int a) throws M68kException {
  5033:        a &= XEiJ.BUS_MOTHER_MASK;
  5034:        if (XEiJ.currentAccelerator == XEiJ.ACCELERATOR_XELLENT30 &&
  5035:            XEiJ.xt3PortAddress <= a && a < XEiJ.xt3PortAddress + 0x4000) {  //Xellent30設定ポート
  5036:          return XEiJ.xt3PortRead () << 16 | XEiJ.xt3PortRead ();
  5037:        }
  5038:        return super.mmdRls (a);  //バスエラー
  5039:      }
  5040:     @Override protected void mmdWb (int a, int d) throws M68kException {
  5041:        a &= XEiJ.BUS_MOTHER_MASK;
  5042:        if (XEiJ.currentAccelerator == XEiJ.ACCELERATOR_XELLENT30 &&
  5043:            XEiJ.xt3PortAddress <= a && a < XEiJ.xt3PortAddress + 0x4000) {  //Xellent30設定ポート
  5044:          if ((a & 1) == 0) {
  5045:          } else {
  5046:            XEiJ.xt3PortWrite (d);
  5047:          }
  5048:          return;
  5049:        }
  5050:        super.mmdWb (a, d);  //バスエラー
  5051:      }
  5052:     @Override protected void mmdWw (int a, int d) throws M68kException {
  5053:        a &= XEiJ.BUS_MOTHER_MASK;
  5054:        if (XEiJ.currentAccelerator == XEiJ.ACCELERATOR_XELLENT30 &&
  5055:            XEiJ.xt3PortAddress <= a && a < XEiJ.xt3PortAddress + 0x4000) {  //Xellent30設定ポート
  5056:          XEiJ.xt3PortWrite (d);
  5057:          return;
  5058:        }
  5059:        super.mmdWw (a, d);  //バスエラー
  5060:      }
  5061:     @Override protected void mmdWl (int a, int d) throws M68kException {
  5062:        a &= XEiJ.BUS_MOTHER_MASK;
  5063:        if (XEiJ.currentAccelerator == XEiJ.ACCELERATOR_XELLENT30 &&
  5064:            XEiJ.xt3PortAddress <= a && a < XEiJ.xt3PortAddress + 0x4000) {  //Xellent30設定ポート
  5065:          XEiJ.xt3PortWrite (d >> 16);
  5066:          XEiJ.xt3PortWrite (d);
  5067:          return;
  5068:        }
  5069:        super.mmdWl (a, d);  //バスエラー
  5070:      }
  5071:   },  //MMD_XB3
  5072: 
  5073:   //--------------------------------------------------------------------------------
  5074:   //MMD_XTM Xellent30のSRAM
  5075:   MMD_XTM {
  5076:     @Override public String toString () {
  5077:       return Multilingual.mlnJapanese ? "Xellent30 の SRAM" : "SRAM on Xellent30";
  5078:     }
  5079:     //ピーク
  5080:     @Override protected byte mmdPbs (int a) {
  5081:       a -= XEiJ.xt3MemoryPosition;
  5082:       return XEiJ.xt3MemoryArray[a];
  5083:     }
  5084:     @Override protected int mmdPbz (int a) {
  5085:       a -= XEiJ.xt3MemoryPosition;
  5086:       return XEiJ.xt3MemoryArray[a] & 0xff;
  5087:     }
  5088:     @Override protected int mmdPws (int a) {
  5089:       a -= XEiJ.xt3MemoryPosition;
  5090:       return XEiJ.xt3MemoryArray[a] << 8 | (XEiJ.xt3MemoryArray[a + 1] & 0xff);
  5091:     }
  5092:     @Override protected int mmdPwz (int a) {
  5093:       a -= XEiJ.xt3MemoryPosition;
  5094:       return (char) (XEiJ.xt3MemoryArray[a] << 8 | (XEiJ.xt3MemoryArray[a + 1] & 0xff));
  5095:     }
  5096:     @Override protected int mmdPls (int a) {
  5097:       a -= XEiJ.xt3MemoryPosition;
  5098:       return XEiJ.xt3MemoryArray[a] << 24 | (XEiJ.xt3MemoryArray[a + 1] & 0xff) << 16 | (char) (XEiJ.xt3MemoryArray[a + 2] << 8 | (XEiJ.xt3MemoryArray[a + 3] & 0xff));
  5099:     }
  5100:     //リード
  5101:     @Override protected byte mmdRbs (int a) throws M68kException {
  5102:        a -= XEiJ.xt3MemoryPosition;
  5103:        return XEiJ.xt3MemoryArray[a];
  5104:      }
  5105:     @Override protected int mmdRbz (int a) throws M68kException {
  5106:        a -= XEiJ.xt3MemoryPosition;
  5107:        return XEiJ.xt3MemoryArray[a] & 0xff;
  5108:      }
  5109:     @Override protected int mmdRws (int a) throws M68kException {
  5110:        a -= XEiJ.xt3MemoryPosition;
  5111:        return XEiJ.xt3MemoryArray[a] << 8 | (XEiJ.xt3MemoryArray[a + 1] & 0xff);
  5112:      }
  5113:     @Override protected int mmdRwz (int a) throws M68kException {
  5114:        a -= XEiJ.xt3MemoryPosition;
  5115:        return (char) (XEiJ.xt3MemoryArray[a] << 8 | (XEiJ.xt3MemoryArray[a + 1] & 0xff));
  5116:      }
  5117:     @Override protected int mmdRls (int a) throws M68kException {
  5118:        a -= XEiJ.xt3MemoryPosition;
  5119:        return XEiJ.xt3MemoryArray[a] << 24 | (XEiJ.xt3MemoryArray[a + 1] & 0xff) << 16 | (char) (XEiJ.xt3MemoryArray[a + 2] << 8 | (XEiJ.xt3MemoryArray[a + 3] & 0xff));
  5120:      }
  5121:     //ライト
  5122:     @Override protected void mmdWb (int a, int d) throws M68kException {
  5123:        a -= XEiJ.xt3MemoryPosition;
  5124:        XEiJ.xt3MemoryArray[a    ] = (byte)  d;
  5125:      }
  5126:     @Override protected void mmdWw (int a, int d) throws M68kException {
  5127:        a -= XEiJ.xt3MemoryPosition;
  5128:        XEiJ.xt3MemoryArray[a    ] = (byte) (d >> 8);
  5129:        XEiJ.xt3MemoryArray[a + 1] = (byte)  d;
  5130:      }
  5131:     @Override protected void mmdWl (int a, int d) throws M68kException {
  5132:        a -= XEiJ.xt3MemoryPosition;
  5133:        XEiJ.xt3MemoryArray[a    ] = (byte) (d >> 24);
  5134:        XEiJ.xt3MemoryArray[a + 1] = (byte) (d >> 16);
  5135:        XEiJ.xt3MemoryArray[a + 2] = (byte) (d >> 8);
  5136:        XEiJ.xt3MemoryArray[a + 3] = (byte)  d;
  5137:      }
  5138:   },  //MMD_XTM
  5139: 
  5140:   //--------------------------------------------------------------------------------
  5141:   //MMD_SMR SRAM
  5142:   MMD_SMR {
  5143:     @Override public String toString () {
  5144:       return Multilingual.mlnJapanese ? "SRAM" : "SRAM";
  5145:     }
  5146:     //ピーク
  5147:     @Override protected byte mmdPbs (int a) {
  5148:       a &= XEiJ.BUS_MOTHER_MASK;
  5149:       return MainMemory.mmrM8[a];
  5150:     }
  5151:     @Override protected int mmdPbz (int a) {
  5152:       a &= XEiJ.BUS_MOTHER_MASK;
  5153:       return MainMemory.mmrM8[a] & 0xff;
  5154:     }
  5155:     @Override protected int mmdPws (int a) {
  5156:       a &= XEiJ.BUS_MOTHER_MASK;
  5157:       if (MainMemory.MMR_USE_BYTE_BUFFER) {
  5158:         return MainMemory.mmrBuffer.getShort (a);
  5159:       } else {
  5160:         return MainMemory.mmrM8[a] << 8 | (MainMemory.mmrM8[a + 1] & 0xff);
  5161:       }
  5162:     }
  5163:     @Override protected int mmdPwz (int a) {
  5164:       a &= XEiJ.BUS_MOTHER_MASK;
  5165:       if (MainMemory.MMR_USE_BYTE_BUFFER) {
  5166:         return MainMemory.mmrBuffer.getChar (a);
  5167:       } else {
  5168:         return (char) (MainMemory.mmrM8[a] << 8 | (MainMemory.mmrM8[a + 1] & 0xff));
  5169:       }
  5170:     }
  5171:     @Override protected int mmdPls (int a) {
  5172:       a &= XEiJ.BUS_MOTHER_MASK;
  5173:       if (MainMemory.MMR_USE_BYTE_BUFFER) {
  5174:         return MainMemory.mmrBuffer.getInt (a);
  5175:       } else {
  5176:         return MainMemory.mmrM8[a] << 24 | (MainMemory.mmrM8[a + 1] & 0xff) << 16 | (char) (MainMemory.mmrM8[a + 2] << 8 | (MainMemory.mmrM8[a + 3] & 0xff));
  5177:       }
  5178:     }
  5179:     //リード
  5180:     @Override protected byte mmdRbs (int a) throws M68kException {
  5181:        XEiJ.mpuClockTime += XEiJ.busWaitTime.sram;
  5182:        a &= XEiJ.BUS_MOTHER_MASK;
  5183:        XEiJ.mpuClockTime += XEiJ.busWaitTime.sram;
  5184:        return MainMemory.mmrM8[a];
  5185:      }
  5186:     @Override protected int mmdRbz (int a) throws M68kException {
  5187:        XEiJ.mpuClockTime += XEiJ.busWaitTime.sram;
  5188:        a &= XEiJ.BUS_MOTHER_MASK;
  5189:        XEiJ.mpuClockTime += XEiJ.busWaitTime.sram;
  5190:        return MainMemory.mmrM8[a] & 0xff;
  5191:      }
  5192:     @Override protected int mmdRws (int a) throws M68kException {
  5193:        return (short) mmdRwz (a);
  5194:      }
  5195:     @Override protected int mmdRwz (int a) throws M68kException {
  5196:        XEiJ.mpuClockTime += XEiJ.busWaitTime.sram;
  5197:        a &= XEiJ.BUS_MOTHER_MASK;
  5198:        XEiJ.mpuClockTime += XEiJ.busWaitTime.sram;
  5199:        int d;
  5200:        if (MainMemory.MMR_USE_BYTE_BUFFER) {
  5201:          d = MainMemory.mmrBuffer.getChar (a);
  5202:        } else {
  5203:          d = (char) (MainMemory.mmrM8[a] << 8 | (MainMemory.mmrM8[a + 1] & 0xff));
  5204:        }
  5205:        return d;
  5206:      }
  5207:     @Override protected int mmdRls (int a) throws M68kException {
  5208:        XEiJ.mpuClockTime += XEiJ.busWaitTime.sram * 2;
  5209:        a &= XEiJ.BUS_MOTHER_MASK;
  5210:        XEiJ.mpuClockTime += XEiJ.busWaitTime.sram * 2;
  5211:        int d;
  5212:        if (MainMemory.MMR_USE_BYTE_BUFFER) {
  5213:          d = MainMemory.mmrBuffer.getInt (a);
  5214:        } else {
  5215:          d = MainMemory.mmrM8[a] << 24 | (MainMemory.mmrM8[a + 1] & 0xff) << 16 | (char) (MainMemory.mmrM8[a + 2] << 8 | (MainMemory.mmrM8[a + 3] & 0xff));
  5216:        }
  5217:        return d;
  5218:      }
  5219:     //ライト
  5220:     @Override protected void mmdWb (int a, int d) throws M68kException {
  5221:        XEiJ.mpuClockTime += XEiJ.busWaitTime.sram;
  5222:        if (SRAM.smrWriteEnableOn) {
  5223:          a &= XEiJ.BUS_MOTHER_MASK;
  5224:          XEiJ.mpuClockTime += XEiJ.busWaitTime.sram;
  5225:          MainMemory.mmrM8[a] = (byte) d;
  5226:          if (a == 0x00ed002b || a == 0x00ed0059) {  //キーボードの配列または字体が変化した
  5227:            Keyboard.kbdRepaint ();  //キーボードが表示されているときkbdImageを作り直して再描画する
  5228:          } else if (a == 0x00ed005a) {  //HDMAX
  5229:            if (0x00fe0000 <= XEiJ.regPC0 && XEiJ.regPC0 <= 0x00ffffff) {  //IPLROMがSRAMのHDMAXを書き換えようとしている 
  5230:              SRAM.smrOverride ();  //SRAMの設定を上書きする
  5231:            }
  5232:          }
  5233:        } else {
  5234:          System.out.printf ("%08X writing $%02X to $%08X in a write-protected state\n", XEiJ.regPC0, d & 0xff, a);
  5235:          if (SRAM.smrSRAMBusErrorOn) {
  5236:            super.mmdWb (a, d);  //バスエラー
  5237:          }
  5238:        }
  5239:      }
  5240:     @Override protected void mmdWw (int a, int d) throws M68kException {
  5241:        XEiJ.mpuClockTime += XEiJ.busWaitTime.sram;
  5242:        if (SRAM.smrWriteEnableOn) {
  5243:          a &= XEiJ.BUS_MOTHER_MASK;
  5244:          XEiJ.mpuClockTime += XEiJ.busWaitTime.sram;
  5245:          MainMemory.mmrM8[a    ] = (byte) (d >> 8);
  5246:          MainMemory.mmrM8[a + 1] = (byte)  d;
  5247:          if (a == (0x00ed002b & -2) || a == (0x00ed0059 & -2)) {  //キーボードの配列または字体が変化した
  5248:            Keyboard.kbdRepaint ();  //キーボードが表示されているときkbdImageを作り直して再描画する
  5249:          }
  5250:        } else {
  5251:          System.out.printf ("%08X writing $%04X to $%08X in a write-protected state\n", XEiJ.regPC0, d & 0xffff, a);
  5252:          if (SRAM.smrSRAMBusErrorOn) {
  5253:            super.mmdWw (a, d);  //バスエラー
  5254:          }
  5255:        }
  5256:      }
  5257:     @Override protected void mmdWl (int a, int d) throws M68kException {
  5258:        if (SRAM.smrWriteEnableOn) {
  5259:          mmdWw (a    , d >> 16);
  5260:          mmdWw (a + 2, d      );
  5261:        } else {
  5262:          System.out.printf ("%08X writing $%08X to $%08X in a write-protected state\n", XEiJ.regPC0, d, a);
  5263:          if (SRAM.smrSRAMBusErrorOn) {
  5264:            super.mmdWl (a, d);  //バスエラー
  5265:          }
  5266:        }
  5267:      }
  5268:   },  //MMD_SMR
  5269: 
  5270:   //--------------------------------------------------------------------------------
  5271:   //MMD_XB4 拡張ボード領域4
  5272:   //  $00EE0000~$00EFFFFF  バンクメモリ
  5273:   MMD_XB4 {
  5274:     @Override public String toString () {
  5275:       return Multilingual.mlnJapanese ? "拡張ボード領域 4" : "Expansion Board Area 4";
  5276:     }
  5277:     //リード
  5278:     @Override protected byte mmdRbs (int a) throws M68kException {
  5279:        if (XEiJ.bnkOn) {
  5280:          a &= XEiJ.BUS_MOTHER_MASK;
  5281:          a = XEiJ.bnkPageStart + (a - 0x00ee0000);
  5282:          return XEiJ.bnkMemory[a];
  5283:        }
  5284:        return super.mmdRbs (a);  //バスエラー
  5285:      }
  5286:     @Override protected int mmdRbz (int a) throws M68kException {
  5287:        if (XEiJ.bnkOn) {
  5288:          a &= XEiJ.BUS_MOTHER_MASK;
  5289:          a = XEiJ.bnkPageStart + (a - 0x00ee0000);
  5290:          return XEiJ.bnkMemory[a] & 0xff;
  5291:        }
  5292:        return super.mmdRbz (a);  //バスエラー
  5293:      }
  5294:     @Override protected int mmdRws (int a) throws M68kException {
  5295:        if (XEiJ.bnkOn) {
  5296:          a &= XEiJ.BUS_MOTHER_MASK;
  5297:          a = XEiJ.bnkPageStart + (a - 0x00ee0000);
  5298:          return ((XEiJ.bnkMemory[a    ]       ) << 8 |
  5299:                  (XEiJ.bnkMemory[a + 1] & 0xff));
  5300:        }
  5301:        return super.mmdRws (a);  //バスエラー
  5302:      }
  5303:     @Override protected int mmdRwz (int a) throws M68kException {
  5304:        if (XEiJ.bnkOn) {
  5305:          a &= XEiJ.BUS_MOTHER_MASK;
  5306:          a = XEiJ.bnkPageStart + (a - 0x00ee0000);
  5307:          return ((XEiJ.bnkMemory[a    ] & 0xff) << 8 |
  5308:                  (XEiJ.bnkMemory[a + 1] & 0xff));
  5309:        }
  5310:        return super.mmdRwz (a);  //バスエラー
  5311:      }
  5312:     @Override protected int mmdRls (int a) throws M68kException {
  5313:        if (XEiJ.bnkOn) {
  5314:          a &= XEiJ.BUS_MOTHER_MASK;
  5315:          a = XEiJ.bnkPageStart + (a - 0x00ee0000);
  5316:          return ((XEiJ.bnkMemory[a    ]       ) << 24 |
  5317:                  (XEiJ.bnkMemory[a + 1] & 0xff) << 16 |
  5318:                  (XEiJ.bnkMemory[a + 2] & 0xff) <<  8 |
  5319:                  (XEiJ.bnkMemory[a + 3] & 0xff));
  5320:        }
  5321:        return super.mmdRls (a);  //バスエラー
  5322:      }
  5323:     //ライト
  5324:     @Override protected void mmdWb (int a, int d) throws M68kException {
  5325:        if (XEiJ.bnkOn) {
  5326:          a &= XEiJ.BUS_MOTHER_MASK;
  5327:          a = XEiJ.bnkPageStart + (a - 0x00ee0000);
  5328:          XEiJ.bnkMemory[a] = (byte) d;
  5329:          return;
  5330:        }
  5331:        super.mmdWb (a, d);  //バスエラー
  5332:      }
  5333:     @Override protected void mmdWw (int a, int d) throws M68kException {
  5334:        if (XEiJ.bnkOn) {
  5335:          a &= XEiJ.BUS_MOTHER_MASK;
  5336:          a = XEiJ.bnkPageStart + (a - 0x00ee0000);
  5337:          XEiJ.bnkMemory[a    ] = (byte) (d >> 8);
  5338:          XEiJ.bnkMemory[a + 1] = (byte)  d;
  5339:          return;
  5340:        }
  5341:        super.mmdWw (a, d);  //バスエラー
  5342:      }
  5343:     @Override protected void mmdWl (int a, int d) throws M68kException {
  5344:        if (XEiJ.bnkOn) {
  5345:          a &= XEiJ.BUS_MOTHER_MASK;
  5346:          a = XEiJ.bnkPageStart + (a - 0x00ee0000);
  5347:          XEiJ.bnkMemory[a    ] = (byte) (d >> 24);
  5348:          XEiJ.bnkMemory[a + 1] = (byte) (d >> 16);
  5349:          XEiJ.bnkMemory[a + 2] = (byte) (d >>  8);
  5350:          XEiJ.bnkMemory[a + 3] = (byte)  d;
  5351:          return;
  5352:        }
  5353:        super.mmdWl (a, d);  //バスエラー
  5354:      }
  5355:   },  //MMD_XB4
  5356: 
  5357:   //--------------------------------------------------------------------------------
  5358:   //MMD_CG1 CGROM1
  5359:   MMD_CG1 {
  5360:     @Override public String toString () {
  5361:       return Multilingual.mlnJapanese ? "CGROM" : "CGROM";
  5362:     }
  5363:     //ピーク
  5364:     @Override protected byte mmdPbs (int a) {
  5365:       a &= XEiJ.BUS_MOTHER_MASK;
  5366:       return MainMemory.mmrM8[a];
  5367:     }
  5368:     @Override protected int mmdPbz (int a) {
  5369:       a &= XEiJ.BUS_MOTHER_MASK;
  5370:       return MainMemory.mmrM8[a] & 0xff;
  5371:     }
  5372:     @Override protected int mmdPws (int a) {
  5373:       a &= XEiJ.BUS_MOTHER_MASK;
  5374:       if (MainMemory.MMR_USE_BYTE_BUFFER) {
  5375:         return MainMemory.mmrBuffer.getShort (a);
  5376:       } else {
  5377:         return MainMemory.mmrM8[a] << 8 | (MainMemory.mmrM8[a + 1] & 0xff);
  5378:       }
  5379:     }
  5380:     @Override protected int mmdPwz (int a) {
  5381:       a &= XEiJ.BUS_MOTHER_MASK;
  5382:       if (MainMemory.MMR_USE_BYTE_BUFFER) {
  5383:         return MainMemory.mmrBuffer.getChar (a);
  5384:       } else {
  5385:         return (char) (MainMemory.mmrM8[a] << 8 | (MainMemory.mmrM8[a + 1] & 0xff));
  5386:       }
  5387:     }
  5388:     @Override protected int mmdPls (int a) {
  5389:       a &= XEiJ.BUS_MOTHER_MASK;
  5390:       if (MainMemory.MMR_USE_BYTE_BUFFER) {
  5391:         return MainMemory.mmrBuffer.getInt (a);
  5392:       } else {
  5393:         return MainMemory.mmrM8[a] << 24 | (MainMemory.mmrM8[a + 1] & 0xff) << 16 | (char) (MainMemory.mmrM8[a + 2] << 8 | (MainMemory.mmrM8[a + 3] & 0xff));
  5394:       }
  5395:     }
  5396:     //リード
  5397:     @Override protected byte mmdRbs (int a) throws M68kException {
  5398:        XEiJ.mpuClockTime += XEiJ.busWaitTime.rom;
  5399:        a &= XEiJ.BUS_MOTHER_MASK;
  5400:        return MainMemory.mmrM8[a];
  5401:      }
  5402:     @Override protected int mmdRbz (int a) throws M68kException {
  5403:        XEiJ.mpuClockTime += XEiJ.busWaitTime.rom;
  5404:        a &= XEiJ.BUS_MOTHER_MASK;
  5405:        return MainMemory.mmrM8[a] & 0xff;
  5406:      }
  5407:     @Override protected int mmdRws (int a) throws M68kException {
  5408:        XEiJ.mpuClockTime += XEiJ.busWaitTime.rom;
  5409:        a &= XEiJ.BUS_MOTHER_MASK;
  5410:        if (MainMemory.MMR_USE_BYTE_BUFFER) {
  5411:          return MainMemory.mmrBuffer.getShort (a);
  5412:        } else {
  5413:          return MainMemory.mmrM8[a] << 8 | (MainMemory.mmrM8[a + 1] & 0xff);
  5414:        }
  5415:      }
  5416:     @Override protected int mmdRwz (int a) throws M68kException {
  5417:        XEiJ.mpuClockTime += XEiJ.busWaitTime.rom;
  5418:        a &= XEiJ.BUS_MOTHER_MASK;
  5419:        if (MainMemory.MMR_USE_BYTE_BUFFER) {
  5420:          return MainMemory.mmrBuffer.getChar (a);
  5421:        } else {
  5422:          return (char) (MainMemory.mmrM8[a] << 8 | (MainMemory.mmrM8[a + 1] & 0xff));
  5423:        }
  5424:      }
  5425:     @Override protected int mmdRls (int a) throws M68kException {
  5426:        XEiJ.mpuClockTime += XEiJ.busWaitTime.romlong;
  5427:        a &= XEiJ.BUS_MOTHER_MASK;
  5428:        if (MainMemory.MMR_USE_BYTE_BUFFER) {
  5429:          return MainMemory.mmrBuffer.getInt (a);
  5430:        } else {
  5431:          return MainMemory.mmrM8[a] << 24 | (MainMemory.mmrM8[a + 1] & 0xff) << 16 | (char) (MainMemory.mmrM8[a + 2] << 8 | (MainMemory.mmrM8[a + 3] & 0xff));
  5432:        }
  5433:      }
  5434:   },  //MMD_CG1
  5435: 
  5436:   //--------------------------------------------------------------------------------
  5437:   //MMD_CG2 CGROM2
  5438:   MMD_CG2 {
  5439:     @Override public String toString () {
  5440:       return Multilingual.mlnJapanese ? "CGROM" : "CGROM";
  5441:     }
  5442:     //ピーク
  5443:     @Override protected byte mmdPbs (int a) {
  5444:       a &= XEiJ.BUS_MOTHER_MASK;
  5445:       return MainMemory.mmrM8[a];
  5446:     }
  5447:     @Override protected int mmdPbz (int a) {
  5448:       a &= XEiJ.BUS_MOTHER_MASK;
  5449:       return MainMemory.mmrM8[a] & 0xff;
  5450:     }
  5451:     @Override protected int mmdPws (int a) {
  5452:       a &= XEiJ.BUS_MOTHER_MASK;
  5453:       if (MainMemory.MMR_USE_BYTE_BUFFER) {
  5454:         return MainMemory.mmrBuffer.getShort (a);
  5455:       } else {
  5456:         return MainMemory.mmrM8[a] << 8 | (MainMemory.mmrM8[a + 1] & 0xff);
  5457:       }
  5458:     }
  5459:     @Override protected int mmdPwz (int a) {
  5460:       a &= XEiJ.BUS_MOTHER_MASK;
  5461:       if (MainMemory.MMR_USE_BYTE_BUFFER) {
  5462:         return MainMemory.mmrBuffer.getChar (a);
  5463:       } else {
  5464:         return (char) (MainMemory.mmrM8[a] << 8 | (MainMemory.mmrM8[a + 1] & 0xff));
  5465:       }
  5466:     }
  5467:     @Override protected int mmdPls (int a) {
  5468:       a &= XEiJ.BUS_MOTHER_MASK;
  5469:       if (MainMemory.MMR_USE_BYTE_BUFFER) {
  5470:         return MainMemory.mmrBuffer.getInt (a);
  5471:       } else {
  5472:         return MainMemory.mmrM8[a] << 24 | (MainMemory.mmrM8[a + 1] & 0xff) << 16 | (char) (MainMemory.mmrM8[a + 2] << 8 | (MainMemory.mmrM8[a + 3] & 0xff));
  5473:       }
  5474:     }
  5475:     //リード
  5476:     @Override protected byte mmdRbs (int a) throws M68kException {
  5477:        XEiJ.mpuClockTime += XEiJ.busWaitTime.rom;
  5478:        a &= XEiJ.BUS_MOTHER_MASK;
  5479:        return MainMemory.mmrM8[a];
  5480:      }
  5481:     @Override protected int mmdRbz (int a) throws M68kException {
  5482:        XEiJ.mpuClockTime += XEiJ.busWaitTime.rom;
  5483:        a &= XEiJ.BUS_MOTHER_MASK;
  5484:        return MainMemory.mmrM8[a] & 0xff;
  5485:      }
  5486:     @Override protected int mmdRws (int a) throws M68kException {
  5487:        XEiJ.mpuClockTime += XEiJ.busWaitTime.rom;
  5488:        a &= XEiJ.BUS_MOTHER_MASK;
  5489:        if (MainMemory.MMR_USE_BYTE_BUFFER) {
  5490:          return MainMemory.mmrBuffer.getShort (a);
  5491:        } else {
  5492:          return MainMemory.mmrM8[a] << 8 | (MainMemory.mmrM8[a + 1] & 0xff);
  5493:        }
  5494:      }
  5495:     @Override protected int mmdRwz (int a) throws M68kException {
  5496:        XEiJ.mpuClockTime += XEiJ.busWaitTime.rom;
  5497:        a &= XEiJ.BUS_MOTHER_MASK;
  5498:        if (MainMemory.MMR_USE_BYTE_BUFFER) {
  5499:          return MainMemory.mmrBuffer.getChar (a);
  5500:        } else {
  5501:          return (char) (MainMemory.mmrM8[a] << 8 | (MainMemory.mmrM8[a + 1] & 0xff));
  5502:        }
  5503:      }
  5504:     @Override protected int mmdRls (int a) throws M68kException {
  5505:        XEiJ.mpuClockTime += XEiJ.busWaitTime.romlong;
  5506:        a &= XEiJ.BUS_MOTHER_MASK;
  5507:        if (MainMemory.MMR_USE_BYTE_BUFFER) {
  5508:          return MainMemory.mmrBuffer.getInt (a);
  5509:        } else {
  5510:          return MainMemory.mmrM8[a] << 24 | (MainMemory.mmrM8[a + 1] & 0xff) << 16 | (char) (MainMemory.mmrM8[a + 2] << 8 | (MainMemory.mmrM8[a + 3] & 0xff));
  5511:        }
  5512:      }
  5513:   },  //MMD_CG2
  5514: 
  5515:   //--------------------------------------------------------------------------------
  5516:   //MMD_ROM ROM
  5517:   MMD_ROM {
  5518:     @Override public String toString () {
  5519:       return Multilingual.mlnJapanese ? "ROM" : "ROM";
  5520:     }
  5521:     //ピーク
  5522:     @Override protected byte mmdPbs (int a) {
  5523:       a &= XEiJ.BUS_MOTHER_MASK;
  5524:       return MainMemory.mmrM8[a];
  5525:     }
  5526:     @Override protected int mmdPbz (int a) {
  5527:       a &= XEiJ.BUS_MOTHER_MASK;
  5528:       return MainMemory.mmrM8[a] & 0xff;
  5529:     }
  5530:     @Override protected int mmdPws (int a) {
  5531:       a &= XEiJ.BUS_MOTHER_MASK;
  5532:       if (MainMemory.MMR_USE_BYTE_BUFFER) {
  5533:         return MainMemory.mmrBuffer.getShort (a);
  5534:       } else {
  5535:         return MainMemory.mmrM8[a] << 8 | (MainMemory.mmrM8[a + 1] & 0xff);
  5536:       }
  5537:     }
  5538:     @Override protected int mmdPwz (int a) {
  5539:       a &= XEiJ.BUS_MOTHER_MASK;
  5540:       if (MainMemory.MMR_USE_BYTE_BUFFER) {
  5541:         return MainMemory.mmrBuffer.getChar (a);
  5542:       } else {
  5543:         return (char) (MainMemory.mmrM8[a] << 8 | (MainMemory.mmrM8[a + 1] & 0xff));
  5544:       }
  5545:     }
  5546:     @Override protected int mmdPls (int a) {
  5547:       a &= XEiJ.BUS_MOTHER_MASK;
  5548:       if (MainMemory.MMR_USE_BYTE_BUFFER) {
  5549:         return MainMemory.mmrBuffer.getInt (a);
  5550:       } else {
  5551:         return MainMemory.mmrM8[a] << 24 | (MainMemory.mmrM8[a + 1] & 0xff) << 16 | (char) (MainMemory.mmrM8[a + 2] << 8 | (MainMemory.mmrM8[a + 3] & 0xff));
  5552:       }
  5553:     }
  5554:     //リード
  5555:     @Override protected byte mmdRbs (int a) throws M68kException {
  5556:        XEiJ.mpuClockTime += XEiJ.busWaitTime.rom;
  5557:        a &= XEiJ.BUS_MOTHER_MASK;
  5558:        return MainMemory.mmrM8[a];
  5559:      }
  5560:     @Override protected int mmdRbz (int a) throws M68kException {
  5561:        XEiJ.mpuClockTime += XEiJ.busWaitTime.rom;
  5562:        a &= XEiJ.BUS_MOTHER_MASK;
  5563:        return MainMemory.mmrM8[a] & 0xff;
  5564:      }
  5565:     @Override protected int mmdRws (int a) throws M68kException {
  5566:        XEiJ.mpuClockTime += XEiJ.busWaitTime.rom;
  5567:        a &= XEiJ.BUS_MOTHER_MASK;
  5568:        if (MainMemory.MMR_USE_BYTE_BUFFER) {
  5569:          return MainMemory.mmrBuffer.getShort (a);
  5570:        } else {
  5571:          return MainMemory.mmrM8[a] << 8 | (MainMemory.mmrM8[a + 1] & 0xff);
  5572:        }
  5573:      }
  5574:     @Override protected int mmdRwz (int a) throws M68kException {
  5575:        XEiJ.mpuClockTime += XEiJ.busWaitTime.rom;
  5576:        a &= XEiJ.BUS_MOTHER_MASK;
  5577:        if (MainMemory.MMR_USE_BYTE_BUFFER) {
  5578:          return MainMemory.mmrBuffer.getChar (a);
  5579:        } else {
  5580:          return (char) (MainMemory.mmrM8[a] << 8 | (MainMemory.mmrM8[a + 1] & 0xff));
  5581:        }
  5582:      }
  5583:     @Override protected int mmdRls (int a) throws M68kException {
  5584:        XEiJ.mpuClockTime += XEiJ.busWaitTime.romlong;
  5585:        a &= XEiJ.BUS_MOTHER_MASK;
  5586:        if (MainMemory.MMR_USE_BYTE_BUFFER) {
  5587:          return MainMemory.mmrBuffer.getInt (a);
  5588:        } else {
  5589:          return MainMemory.mmrM8[a] << 24 | (MainMemory.mmrM8[a + 1] & 0xff) << 16 | (char) (MainMemory.mmrM8[a + 2] << 8 | (MainMemory.mmrM8[a + 3] & 0xff));
  5590:        }
  5591:      }
  5592:   },  //MMD_ROM
  5593: 
  5594:   //--------------------------------------------------------------------------------
  5595:   //MMD_IBP 命令ブレークポイント
  5596:   MMD_IBP {
  5597:     @Override public String toString () {
  5598:       return Multilingual.mlnJapanese ? "命令ブレークポイント" : "Instruction Break Point";
  5599:     }
  5600:     @Override protected int mmdRwz (int a) throws M68kException {
  5601:        if (InstructionBreakPoint.IBP_ON) {
  5602:          InstructionBreakPoint.InstructionBreakRecord[] hashTable = (XEiJ.regSRS != 0 ?
  5603:                                                                      InstructionBreakPoint.ibpSuperHashTable :
  5604:                                                                      InstructionBreakPoint.ibpUserHashTable);
  5605:          for (InstructionBreakPoint.InstructionBreakRecord r = hashTable[a >> 1 & InstructionBreakPoint.IBP_HASH_MASK];
  5606:               r != null;
  5607:               r = r.ibrNext) {  //同じ物理ハッシュコードを持つ命令ブレークポイントについて
  5608:            if (r.ibrPhysicalAddress == a) {  //命令ブレークポイントが設定されているとき
  5609:              if (r.ibrValue == r.ibrTarget) {  //現在値が目標値と一致しているとき
  5610:                if (r.ibrThreshold < 0) {  //インスタントのとき
  5611:                  InstructionBreakPoint.ibpRemove (r.ibrLogicalAddress, XEiJ.regSRS);  //取り除く
  5612:                  XEiJ.mpuContinue = true;  //ステップ実行を継続する
  5613:                } else if (r.ibrTarget < r.ibrThreshold) {  //インスタント化しているとき
  5614:                  r.ibrTarget = r.ibrThreshold;  //目標値を閾値に戻す
  5615:                  XEiJ.mpuContinue = true;  //ステップ実行を継続する
  5616:                } else {  //インスタントでなくインスタント化していないとき
  5617:                  if (r.ibrScriptElement != null &&  //スクリプトが指定されていて
  5618:                      r.ibrScriptElement.exlEval (ExpressionEvaluator.EVM_EXPRESSION).exlFloatValue.iszero ()) {  //条件が成立していないとき
  5619:                    break;  //続行する
  5620:                  }
  5621:                  r.ibrTarget++;  //目標値を増やす
  5622:                  XEiJ.mpuContinue = false;  //ステップ実行を継続しない
  5623:                }
  5624:                M68kException.m6eNumber = -1;  //命令ブレークポイントによる停止。XEiJ.mpuContinueを設定すること
  5625:                throw M68kException.m6eSignal;  //停止する
  5626:              } else {  //現在値が目標値と一致していないとき
  5627:                r.ibrValue++;  //現在値を増やす
  5628:                break;  //続行する
  5629:              }
  5630:            }
  5631:          }
  5632:        }
  5633:        if (DataBreakPoint.DBP_ON) {
  5634:          return DataBreakPoint.dbpMemoryMap[a >>> XEiJ.BUS_PAGE_BITS].mmdRwz (a);
  5635:        } else {
  5636:          return XEiJ.busMemoryMap[a >>> XEiJ.BUS_PAGE_BITS].mmdRwz (a);
  5637:        }
  5638:      }
  5639:   },  //MMD_IBP
  5640: 
  5641:   //--------------------------------------------------------------------------------
  5642:   //MMD_DBP データブレークポイント
  5643:   MMD_DBP {
  5644:     @Override public String toString () {
  5645:       return Multilingual.mlnJapanese ? "データブレークポイント" : "Data Break Point";
  5646:     }
  5647:     //ピーク
  5648:     @Override protected byte mmdPbs (int a) {
  5649:       return (XEiJ.regSRS != 0 ? XEiJ.busSuperMap : XEiJ.busUserMap)[a >>> XEiJ.BUS_PAGE_BITS].mmdPbs (a);
  5650:     }
  5651:     @Override protected int mmdPbz (int a) {
  5652:       return (XEiJ.regSRS != 0 ? XEiJ.busSuperMap : XEiJ.busUserMap)[a >>> XEiJ.BUS_PAGE_BITS].mmdPbz (a);
  5653:     }
  5654:     @Override protected int mmdPws (int a) {
  5655:       return (XEiJ.regSRS != 0 ? XEiJ.busSuperMap : XEiJ.busUserMap)[a >>> XEiJ.BUS_PAGE_BITS].mmdPws (a);
  5656:     }
  5657:     @Override protected int mmdPwz (int a) {
  5658:       return (XEiJ.regSRS != 0 ? XEiJ.busSuperMap : XEiJ.busUserMap)[a >>> XEiJ.BUS_PAGE_BITS].mmdPwz (a);
  5659:     }
  5660:     @Override protected int mmdPls (int a) {
  5661:       return (XEiJ.regSRS != 0 ? XEiJ.busSuperMap : XEiJ.busUserMap)[a >>> XEiJ.BUS_PAGE_BITS].mmdPls (a);
  5662:     }
  5663:     //リード
  5664:     @Override protected byte mmdRbs (int a) throws M68kException {
  5665:        int d = (XEiJ.regSRS != 0 ? XEiJ.busSuperMap : XEiJ.busUserMap)[a >>> XEiJ.BUS_PAGE_BITS].mmdRbs (a);
  5666:        DataBreakPoint.dbpBreak (DataBreakPoint.DBP_BYTE, a, d);
  5667:        return (byte) d;
  5668:      }
  5669:     @Override protected int mmdRbz (int a) throws M68kException {
  5670:        int d = (XEiJ.regSRS != 0 ? XEiJ.busSuperMap : XEiJ.busUserMap)[a >>> XEiJ.BUS_PAGE_BITS].mmdRbz (a);
  5671:        DataBreakPoint.dbpBreak (DataBreakPoint.DBP_BYTE, a, d);
  5672:        return d;
  5673:      }
  5674:     @Override protected int mmdRws (int a) throws M68kException {
  5675:        int d = (XEiJ.regSRS != 0 ? XEiJ.busSuperMap : XEiJ.busUserMap)[a >>> XEiJ.BUS_PAGE_BITS].mmdRws (a);
  5676:        DataBreakPoint.dbpBreak (DataBreakPoint.DBP_WORD, a, d);
  5677:        return d;
  5678:      }
  5679:     @Override protected int mmdRwz (int a) throws M68kException {
  5680:        int d = (XEiJ.regSRS != 0 ? XEiJ.busSuperMap : XEiJ.busUserMap)[a >>> XEiJ.BUS_PAGE_BITS].mmdRwz (a);
  5681:        DataBreakPoint.dbpBreak (DataBreakPoint.DBP_WORD, a, d);
  5682:        return d;
  5683:      }
  5684:     @Override protected int mmdRls (int a) throws M68kException {
  5685:        int d = (XEiJ.regSRS != 0 ? XEiJ.busSuperMap : XEiJ.busUserMap)[a >>> XEiJ.BUS_PAGE_BITS].mmdRls (a);
  5686:        DataBreakPoint.dbpBreak (DataBreakPoint.DBP_LONG, a, d);
  5687:        return d;
  5688:      }
  5689:     //ライト
  5690:     @Override protected void mmdWb (int a, int d) throws M68kException {
  5691:        (XEiJ.regSRS != 0 ? XEiJ.busSuperMap : XEiJ.busUserMap)[a >>> XEiJ.BUS_PAGE_BITS].mmdWb (a, d);
  5692:        DataBreakPoint.dbpBreak (DataBreakPoint.DBP_BYTE, a, d);
  5693:      }
  5694:     @Override protected void mmdWw (int a, int d) throws M68kException {
  5695:        (XEiJ.regSRS != 0 ? XEiJ.busSuperMap : XEiJ.busUserMap)[a >>> XEiJ.BUS_PAGE_BITS].mmdWw (a, d);
  5696:        DataBreakPoint.dbpBreak (DataBreakPoint.DBP_WORD, a, d);
  5697:      }
  5698:     @Override protected void mmdWl (int a, int d) throws M68kException {
  5699:        (XEiJ.regSRS != 0 ? XEiJ.busSuperMap : XEiJ.busUserMap)[a >>> XEiJ.BUS_PAGE_BITS].mmdWl (a, d);
  5700:        DataBreakPoint.dbpBreak (DataBreakPoint.DBP_LONG, a, d);
  5701:      }
  5702:   },  //MMD_DBP
  5703: 
  5704:   //--------------------------------------------------------------------------------
  5705:   //MMD_NUL ヌルデバイス
  5706:   MMD_NUL {
  5707:     @Override public String toString () {
  5708:       return Multilingual.mlnJapanese ? "ヌルデバイス" : "Null Device";
  5709:     }
  5710:   };  //MMD_NUL
  5711: 
  5712:   //--------------------------------------------------------------------------------
  5713:   //ピークのデフォルト
  5714:   //  エラーや副作用なしでリードする
  5715:   //  バスエラーのときは-1をキャストした値を返す
  5716:   //  リードがデバイスの状態を変化させる可能性がある場合は個別に処理すること
  5717:   protected byte mmdPbs (int a) {
  5718:     try {
  5719:       return (byte) mmdRbz (a);
  5720:     } catch (M68kException e) {
  5721:     }
  5722:     return -1;
  5723:   }
  5724:   protected int mmdPbz (int a) {
  5725:     try {
  5726:       return mmdRbz (a);
  5727:     } catch (M68kException e) {
  5728:     }
  5729:     return 0xff;
  5730:   }
  5731:   protected int mmdPws (int a) {
  5732:     try {
  5733:       return (short) mmdRwz (a);
  5734:     } catch (M68kException e) {
  5735:     }
  5736:     return -1;
  5737:   }
  5738:   protected int mmdPwz (int a) {
  5739:     try {
  5740:       return mmdRwz (a);
  5741:     } catch (M68kException e) {
  5742:     }
  5743:     return 0xffff;
  5744:   }
  5745:   protected int mmdPls (int a) {
  5746:     try {
  5747:       return mmdRls (a);
  5748:     } catch (M68kException e) {
  5749:     }
  5750:     return -1;
  5751:   }
  5752:   //リードのデフォルト
  5753:   //  バイトとワードの符号拡張はゼロ拡張を呼び出す
  5754:   //  符号なしとロングはバスエラー
  5755:   protected byte mmdRbs (int a) throws M68kException {
  5756:     return (byte) mmdRbz (a);
  5757:   }
  5758:   protected int mmdRbz (int a) throws M68kException {
  5759:     M68kException.m6eFSLW |= M68kException.M6E_FSLW_BUS_ERROR_ON_READ;  //サイズは設定済み。分割されている場合があることに注意
  5760:     M68kException.m6eNumber = M68kException.M6E_ACCESS_FAULT;
  5761:     M68kException.m6eAddress = a;
  5762:     M68kException.m6eDirection = XEiJ.MPU_WR_READ;
  5763:     M68kException.m6eSize = XEiJ.MPU_SS_BYTE;
  5764:     throw M68kException.m6eSignal;
  5765:   }
  5766:   protected int mmdRws (int a) throws M68kException {
  5767:     return (short) mmdRwz (a);
  5768:   }
  5769:   protected int mmdRwz (int a) throws M68kException {
  5770:     M68kException.m6eFSLW |= M68kException.M6E_FSLW_BUS_ERROR_ON_READ;  //サイズは設定済み。分割されている場合があることに注意
  5771:     M68kException.m6eNumber = M68kException.M6E_ACCESS_FAULT;
  5772:     M68kException.m6eAddress = a;
  5773:     M68kException.m6eDirection = XEiJ.MPU_WR_READ;
  5774:     M68kException.m6eSize = XEiJ.MPU_SS_WORD;
  5775:     throw M68kException.m6eSignal;
  5776:   }
  5777:   protected int mmdRls (int a) throws M68kException {
  5778:     M68kException.m6eFSLW |= M68kException.M6E_FSLW_BUS_ERROR_ON_READ;  //サイズは設定済み。分割されている場合があることに注意
  5779:     M68kException.m6eNumber = M68kException.M6E_ACCESS_FAULT;
  5780:     M68kException.m6eAddress = a;
  5781:     M68kException.m6eDirection = XEiJ.MPU_WR_READ;
  5782:     M68kException.m6eSize = XEiJ.MPU_SS_LONG;
  5783:     throw M68kException.m6eSignal;
  5784:   }
  5785:   //ポークのデフォルト
  5786:   //  エラーや副作用なしでライトする
  5787:   //  ライトがデバイスの状態を変化させる可能性がある場合は個別に処理すること
  5788:   protected void mmdVb (int a, int d) {
  5789:     try {
  5790:       mmdWb (a, d);
  5791:     } catch (M68kException e) {
  5792:     }
  5793:   }
  5794:   protected void mmdVw (int a, int d) {
  5795:     try {
  5796:       mmdWw (a, d);
  5797:     } catch (M68kException e) {
  5798:     }
  5799:   }
  5800:   protected void mmdVl (int a, int d) {
  5801:     try {
  5802:       mmdWl (a, d);
  5803:     } catch (M68kException e) {
  5804:     }
  5805:   }
  5806:   //ライトのデフォルト
  5807:   //  すべてバスエラー
  5808:   protected void mmdWb (int a, int d) throws M68kException {
  5809:     M68kException.m6eFSLW |= M68kException.M6E_FSLW_BUS_ERROR_ON_WRITE;  //サイズは設定済み。分割されている場合があることに注意
  5810:     M68kException.m6eNumber = M68kException.M6E_ACCESS_FAULT;
  5811:     M68kException.m6eAddress = a;
  5812:     M68kException.m6eDirection = XEiJ.MPU_WR_WRITE;
  5813:     M68kException.m6eSize = XEiJ.MPU_SS_BYTE;
  5814:     throw M68kException.m6eSignal;
  5815:   }
  5816:   protected void mmdWw (int a, int d) throws M68kException {
  5817:     M68kException.m6eFSLW |= M68kException.M6E_FSLW_BUS_ERROR_ON_WRITE;  //サイズは設定済み。分割されている場合があることに注意
  5818:     M68kException.m6eNumber = M68kException.M6E_ACCESS_FAULT;
  5819:     M68kException.m6eAddress = a;
  5820:     M68kException.m6eDirection = XEiJ.MPU_WR_WRITE;
  5821:     M68kException.m6eSize = XEiJ.MPU_SS_WORD;
  5822:     throw M68kException.m6eSignal;
  5823:   }
  5824:   protected void mmdWl (int a, int d) throws M68kException {
  5825:     M68kException.m6eFSLW |= M68kException.M6E_FSLW_BUS_ERROR_ON_WRITE;  //サイズは設定済み。分割されている場合があることに注意
  5826:     M68kException.m6eNumber = M68kException.M6E_ACCESS_FAULT;
  5827:     M68kException.m6eAddress = a;
  5828:     M68kException.m6eDirection = XEiJ.MPU_WR_WRITE;
  5829:     M68kException.m6eSize = XEiJ.MPU_SS_LONG;
  5830:     throw M68kException.m6eSignal;
  5831:   }
  5832: }  //enum MemoryMappedDevice
  5833: 
  5834: 
  5835: