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