SRAM.java
     1: //========================================================================================
     2: //  SRAM.java
     3: //    en:SRAM
     4: //    ja:SRAM
     5: //  Copyright (C) 2003-2025 Makoto Kamada
     6: //
     7: //  This file is part of the XEiJ (X68000 Emulator in Java).
     8: //  You can use, modify and redistribute the XEiJ if the conditions are met.
     9: //  Read the XEiJ License for more details.
    10: //  https://stdkmd.net/xeij/
    11: //========================================================================================
    12: 
    13: package xeij;
    14: 
    15: import java.awt.event.*;  //ActionEvent,ActionListener
    16: import java.io.*;  //File
    17: import java.util.*;  //Arrays
    18: import javax.swing.*;  //JMenu,JRadioButtonMenuItem
    19: 
    20: public class SRAM {
    21: 
    22:   public static int smrSramSizeRequest;  //SRAMのサイズ。16384,32768,65536のいずれか
    23:   public static int smrSramCurrentSize;  //現在のSRAMのサイズ。16384,32768,65536のいずれか
    24: 
    25:   public static String smrSramName;  //SRAMイメージファイル名
    26: 
    27:   public static int smrBootDevice;  //起動デバイス。0x00ed0018。0x0000=STD,0x9070~0x9370=FDn,0x8000~0x8f00=HDn,0xa000=ROM,0xb000=RAM,-1=設定しない
    28:   public static int smrROMBootHandle;  //ROM起動ハンドル。0x00ed000c。-1=設定しない
    29:   public static int smrRAMBootAddress;  //RAM起動アドレス。0x00ed0010。-1=設定しない
    30: 
    31:   public static int smrRepeatDelay;  //リピート開始。0x00ed003a。-1=設定しない,0..15=200+100*n(ms)
    32:   public static int smrRepeatInterval;  //リピート間隔。0x00ed003b。-1=設定しない,0..15=30+5*n^2(ms)
    33:   public static boolean smrWriteEnableOn;  //true=SRAM書き込み可
    34: 
    35:   //-romdb
    36:   public static int smrRomdbFlag;  //ROMデバッガ起動フラグ。0x00ed0058。-1=設定しない,0=OFF,255=AUX,1=CON(IPLROM 1.6のみ)
    37: 
    38:   //-setmemorysize
    39:   public static boolean smrModifyMemorySizeOn;  //SRAMにあるメモリサイズを修正する
    40: 
    41:   //-srambuserror
    42:   public static boolean smrSRAMBusErrorOn;  //SRAMへの書き込み時のバスエラー
    43: 
    44:   public static JMenu smrRepeatDelayMenu;  //リピート開始メニュー
    45:   public static JMenu smrRepeatIntervalMenu;  //リピート間隔メニュー
    46:   public static JMenu smrRomdbMenu;  //ROMデバッガ起動フラグメニュー
    47:   public static JMenuItem smrModifyMemorySizeMenuItem;  //メモリサイズ修正
    48:   public static JMenu smrMenu;  //SRAMメニュー
    49:   public static JMenu smrBootMenu;  //起動デバイスメニュー
    50:   public static JRadioButtonMenuItem smrSTDMenuItem;
    51: 
    52:   //smrInit ()
    53:   //  SRAMを初期化する
    54:   public static void smrInit () {
    55: 
    56:     //-sramsize
    57:     int sizeKB = Settings.sgsGetInt ("sramsize");  //SRAMのサイズ
    58:     smrSramSizeRequest = (sizeKB == 16 ||
    59:                           sizeKB == 32 ||
    60:                           sizeKB == 64 ? sizeKB << 10 : 16 << 10);
    61:     smrSramCurrentSize = smrSramSizeRequest;
    62:     System.out.printf (Multilingual.mlnJapanese ?
    63:                        "SRAM のサイズは %dKB です\n" :
    64:                        "SRAM size is %dKB\n",
    65:                        smrSramSizeRequest >> 10);
    66: 
    67:     boolean initialized = false;
    68: 
    69:     //-sram
    70:     smrSramName = "";
    71:     if (!initialized) {
    72:       smrSramName = Settings.sgsGetString ("sram");  //SRAMイメージファイル名
    73:       if (smrSramName.length () != 0) {
    74:         byte[] array = XEiJ.rscGetFile (smrSramName, smrSramSizeRequest);
    75:         if (array != null) {
    76:           System.arraycopy (array, 0, MainMemory.mmrM8, 0x00ed0000, smrSramSizeRequest);
    77:           if (smrSramSizeRequest < 64 << 10) {
    78:             Arrays.fill (MainMemory.mmrM8, 0x00ed0000 + smrSramSizeRequest, 0x00ed0000 + (64 << 10), (byte) 0);  //範囲外をゼロクリアする
    79:           }
    80:           initialized = true;
    81:         }
    82:       }
    83:     }
    84: 
    85:     //-sramdata
    86:     //  マジックの有無に関係なく復元する
    87:     if (!initialized) {
    88:       byte[] array = Settings.sgsGetData ("sramdata");  //SRAMの内容(gzip+base64)
    89:       if (array.length != 0) {  //復元するデータがある
    90:         System.out.println (Multilingual.mlnJapanese ?
    91:                             "SRAM のデータを復元します" :
    92:                             "SRAM data is restored");
    93:         System.arraycopy (array, 0, MainMemory.mmrM8, 0x00ed0000, Math.min (array.length, smrSramSizeRequest));
    94:         if (array.length < smrSramSizeRequest) {
    95:           Arrays.fill (MainMemory.mmrM8, 0x00ed0000 + array.length, 0x00ed0000 + smrSramSizeRequest, (byte) 0);  //復元されなかった部分をゼロクリアする
    96:         }
    97:         if (smrSramSizeRequest < 64 << 10) {
    98:           Arrays.fill (MainMemory.mmrM8, 0x00ed0000 + smrSramSizeRequest, 0x00ed0000 + (64 << 10), (byte) 0);  //範囲外をゼロクリアする
    99:         }
   100:         initialized = true;
   101:       }
   102:     }
   103: 
   104:     if (!initialized) {
   105:       System.out.println (Multilingual.mlnJapanese ?
   106:                           "SRAM をゼロクリアします" :
   107:                           "SRAM is zero-cleared");
   108:       Arrays.fill (MainMemory.mmrM8, 0x00ed0000, 0x00ed0000 + (64 << 10), (byte) 0);  //ゼロクリアする
   109:       initialized = true;
   110:     }
   111: 
   112:     //-keydly
   113:     int repeatDelay = Settings.sgsGetInt ("keydly");
   114:     smrRepeatDelay = -1 <= repeatDelay && repeatDelay <= 15 ? repeatDelay : -1;
   115: 
   116:     //-keyrep
   117:     int repeatInterval = Settings.sgsGetInt ("keyrep");
   118:     smrRepeatInterval = -1 <= repeatInterval && repeatInterval <= 15 ? repeatInterval : -1;
   119: 
   120:     //-romdb
   121:     {
   122:       String s = Settings.sgsGetString ("romdb").toLowerCase ();
   123:       smrRomdbFlag = (s.equals ("off") ? 0 :
   124:                       s.equals ("on") || s.equals ("aux") ? 255 :
   125:                       s.equals ("con") ? 1 :
   126:                       -1);
   127:     }
   128: 
   129:     //-modifymemorysize
   130:     smrModifyMemorySizeOn = Settings.sgsGetOnOff ("modifymemorysize");
   131: 
   132:     //-srambuserror
   133:     smrSRAMBusErrorOn = Settings.sgsGetOnOff ("srambuserror");
   134: 
   135:     //-boot
   136:     smrParseBootDevice (Settings.sgsGetString ("boot"));
   137: 
   138:   }  //smrInit
   139: 
   140:   //smrTini ()
   141:   //  SRAMの後始末
   142:   public static void smrTini () {
   143: 
   144:     //-sramsize
   145:     Settings.sgsPutInt ("sramsize", smrSramSizeRequest >> 10);
   146: 
   147:     //-sram
   148:     Settings.sgsPutString ("sram", smrSramName);
   149: 
   150:     //-sramdata
   151:     //  マジックの有無に関係なく保存する
   152:     //  常に64KB保存する
   153:     Settings.sgsPutData ("sramdata", MainMemory.mmrM8, 0x00ed0000, 64 << 10);
   154: 
   155:     //-keydly
   156:     Settings.sgsPutInt ("keydly", smrRepeatDelay);  //リピート開始
   157: 
   158:     //-keyrep
   159:     Settings.sgsPutInt ("keyrep", smrRepeatInterval);  //リピート間隔
   160: 
   161:     //-romdb
   162:     Settings.sgsPutString ("romdb",
   163:                            smrRomdbFlag == 0 ? "off" :
   164:                            smrRomdbFlag == 255 ? "aux" :
   165:                            smrRomdbFlag == 1 ? "con" :
   166:                            "");
   167: 
   168:     //-modifymemorysize
   169:     Settings.sgsPutOnOff ("modifymemorysize", smrModifyMemorySizeOn);
   170: 
   171:     //-srambuserror
   172:     Settings.sgsPutOnOff ("srambuserror", smrSRAMBusErrorOn);
   173: 
   174:     //-boot
   175:     Settings.sgsPutString ("boot",
   176:                            smrBootDevice == -1 ? "default" :
   177:                            smrBootDevice == 0x0000 ? "std" :
   178:                            (smrBootDevice & 0xf000) == 0x9000 ? "fd" + (smrBootDevice >> 8 & 3) :
   179:                            (smrBootDevice & 0xf000) == 0x8000 ? "hd" + (smrBootDevice >> 8 & 15) :
   180:                            smrBootDevice == 0xa000 ?
   181:                            (smrROMBootHandle & ~(7 << 2)) == SPC.SPC_HANDLE_EX ? "sc" + (smrROMBootHandle >> 2 & 7) :
   182:                            (smrROMBootHandle & ~(7 << 2)) == SPC.SPC_HANDLE_IN ? "sc" + (smrROMBootHandle >> 2 & 7) :
   183:                            smrROMBootHandle == HFS.HFS_BOOT_HANDLE ? "hf" + HFS.hfsBootUnit :
   184:                            String.format ("rom$%08X", smrROMBootHandle) :
   185:                            smrBootDevice == 0xb000 ? String.format ("ram$%08X", smrRAMBootAddress) :
   186:                            "");
   187: 
   188:   }
   189: 
   190:   public static void smrMakeMenu () {
   191: 
   192:     //アクションリスナー
   193:     ActionListener listener = new ActionListener () {
   194:       @Override public void actionPerformed (ActionEvent ae) {
   195:         Object source = ae.getSource ();
   196:         String command = ae.getActionCommand ();
   197:         switch (command) {
   198:           //メモリサイズ修正
   199:         case "Modify the memory size in SRAM":  //SRAM にあるメモリサイズを修正する
   200:           smrModifyMemorySizeOn = ((JCheckBoxMenuItem) source).isSelected ();
   201:           break;
   202:           //SRAMメニュー
   203:         case "Zero-clear":  //SRAM をゼロクリア
   204:           smrClear ();
   205:           break;
   206:         case "Import":  //SRAM をインポート
   207:           smrLoad ();
   208:           break;
   209:         case "Export":  //SRAM をエクスポート
   210:           smrSave ();
   211:           break;
   212:         case "16KB":
   213:           smrSramSizeRequest = 16384;
   214:           break;
   215:         case "32KB":
   216:           smrSramSizeRequest = 32768;
   217:           break;
   218:         case "64KB":
   219:           smrSramSizeRequest = 65536;
   220:           break;
   221:         case "Bus error when writing to SRAM":  //SRAM への書き込み時のバスエラー
   222:           smrSRAMBusErrorOn = ((JCheckBoxMenuItem) source).isSelected ();
   223:           break;
   224:         default:
   225:           System.out.println ("unknown action command " + command);
   226:         }
   227:       }
   228:     };
   229: 
   230:     //リピート開始メニュー
   231:     ActionListener delayListener = new ActionListener () {
   232:       @Override public void actionPerformed (ActionEvent ae) {
   233:         String command = ae.getActionCommand ();
   234:         switch (command) {
   235:         case "Follow settings in SWITCH.X":  //SWITCH.X の設定に従う
   236:           smrRepeatDelay = -1;
   237:           Keyboard.kbdSetRepeatDelay (MainMemory.mmrRbs (0x00ed003a));
   238:           break;
   239:         case (200 + 100 *  0) + "ms":
   240:         case (200 + 100 *  1) + "ms":
   241:         case (200 + 100 *  2) + "ms":
   242:         case (200 + 100 *  3) + "ms":
   243:         case (200 + 100 *  4) + "ms":
   244:         case (200 + 100 *  5) + "ms":
   245:         case (200 + 100 *  6) + "ms":
   246:         case (200 + 100 *  7) + "ms":
   247:         case (200 + 100 *  8) + "ms":
   248:         case (200 + 100 *  9) + "ms":
   249:         case (200 + 100 * 10) + "ms":
   250:         case (200 + 100 * 11) + "ms":
   251:         case (200 + 100 * 12) + "ms":
   252:         case (200 + 100 * 13) + "ms":
   253:         case (200 + 100 * 14) + "ms":
   254:         case (200 + 100 * 15) + "ms":
   255:           {
   256:             int ms = Integer.parseInt (command.substring (0, command.length () - 2));  //200..1700
   257:             //perl optdiv.pl 1500 100
   258:             //  x/100==x*1311>>>17 (0<=x<=4698) [1500*1311==1966500]
   259:             smrRepeatDelay = (ms - 200) * 1311 >>> 17;  //0..15
   260:             Keyboard.kbdSetRepeatDelay (smrRepeatDelay);
   261:             MainMemory.mmrWb (0x00ed003a, smrRepeatDelay);
   262:           }
   263:           break;
   264:         default:
   265:           System.out.println ("unknown action command " + command);
   266:         }
   267:       }
   268:     };
   269:     ButtonGroup delayGroup = new ButtonGroup ();
   270:     smrRepeatDelayMenu =
   271:       Multilingual.mlnText (
   272:         ComponentFactory.createMenu (
   273:           "Repeat delay",
   274:           Multilingual.mlnText (
   275:             ComponentFactory.createRadioButtonMenuItem (delayGroup, smrRepeatDelay == -1, "Follow settings in SWITCH.X", delayListener),
   276:             "ja", "SWITCH.X の設定に従う"),
   277:           ComponentFactory.createRadioButtonMenuItem (delayGroup, smrRepeatDelay ==  0, (200 + 100 *  0) + "ms", delayListener),
   278:           ComponentFactory.createRadioButtonMenuItem (delayGroup, smrRepeatDelay ==  1, (200 + 100 *  1) + "ms", delayListener),
   279:           ComponentFactory.createRadioButtonMenuItem (delayGroup, smrRepeatDelay ==  2, (200 + 100 *  2) + "ms", delayListener),
   280:           ComponentFactory.createRadioButtonMenuItem (delayGroup, smrRepeatDelay ==  3, (200 + 100 *  3) + "ms", delayListener),
   281:           ComponentFactory.createRadioButtonMenuItem (delayGroup, smrRepeatDelay ==  4, (200 + 100 *  4) + "ms", delayListener),
   282:           ComponentFactory.createRadioButtonMenuItem (delayGroup, smrRepeatDelay ==  5, (200 + 100 *  5) + "ms", delayListener),
   283:           ComponentFactory.createRadioButtonMenuItem (delayGroup, smrRepeatDelay ==  6, (200 + 100 *  6) + "ms", delayListener),
   284:           ComponentFactory.createRadioButtonMenuItem (delayGroup, smrRepeatDelay ==  7, (200 + 100 *  7) + "ms", delayListener),
   285:           ComponentFactory.createRadioButtonMenuItem (delayGroup, smrRepeatDelay ==  8, (200 + 100 *  8) + "ms", delayListener),
   286:           ComponentFactory.createRadioButtonMenuItem (delayGroup, smrRepeatDelay ==  9, (200 + 100 *  9) + "ms", delayListener),
   287:           ComponentFactory.createRadioButtonMenuItem (delayGroup, smrRepeatDelay == 10, (200 + 100 * 10) + "ms", delayListener),
   288:           ComponentFactory.createRadioButtonMenuItem (delayGroup, smrRepeatDelay == 11, (200 + 100 * 11) + "ms", delayListener),
   289:           ComponentFactory.createRadioButtonMenuItem (delayGroup, smrRepeatDelay == 12, (200 + 100 * 12) + "ms", delayListener),
   290:           ComponentFactory.createRadioButtonMenuItem (delayGroup, smrRepeatDelay == 13, (200 + 100 * 13) + "ms", delayListener),
   291:           ComponentFactory.createRadioButtonMenuItem (delayGroup, smrRepeatDelay == 14, (200 + 100 * 14) + "ms", delayListener),
   292:           ComponentFactory.createRadioButtonMenuItem (delayGroup, smrRepeatDelay == 15, (200 + 100 * 15) + "ms", delayListener)
   293:           ),
   294:         "ja", "リピート開始");
   295: 
   296:     //リピート間隔メニュー
   297:     ActionListener intervalListener = new ActionListener () {
   298:       @Override public void actionPerformed (ActionEvent ae) {
   299:         String command = ae.getActionCommand ();
   300:         switch (command) {
   301:         case "Follow settings in SWITCH.X":  //SWITCH.X の設定に従う
   302:           smrRepeatInterval =  -1;
   303:           Keyboard.kbdSetRepeatInterval (MainMemory.mmrRbs (0x00ed003b));
   304:           break;
   305:         case (30 + 5 *  0 *  0) + "ms":
   306:         case (30 + 5 *  1 *  1) + "ms":
   307:         case (30 + 5 *  2 *  2) + "ms":
   308:         case (30 + 5 *  3 *  3) + "ms":
   309:         case (30 + 5 *  4 *  4) + "ms":
   310:         case (30 + 5 *  5 *  5) + "ms":
   311:         case (30 + 5 *  6 *  6) + "ms":
   312:         case (30 + 5 *  7 *  7) + "ms":
   313:         case (30 + 5 *  8 *  8) + "ms":
   314:         case (30 + 5 *  9 *  9) + "ms":
   315:         case (30 + 5 * 10 * 10) + "ms":
   316:         case (30 + 5 * 11 * 11) + "ms":
   317:         case (30 + 5 * 12 * 12) + "ms":
   318:         case (30 + 5 * 13 * 13) + "ms":
   319:         case (30 + 5 * 14 * 14) + "ms":
   320:         case (30 + 5 * 15 * 15) + "ms":
   321:           {
   322:             int ms = Integer.parseInt (command.substring (0, command.length () - 2));  //30..1155
   323:             //perl optdiv.pl 1125 5
   324:             //  x/5==x*1639>>>13 (0<=x<=2733) [1125*1639==1843875]
   325:             smrRepeatInterval = (int) Math.sqrt ((double) ((ms - 30) * 1639 >>> 13));  //0..15
   326:             Keyboard.kbdSetRepeatInterval (smrRepeatInterval);
   327:             MainMemory.mmrWb (0x00ed003b, smrRepeatInterval);
   328:           }
   329:           break;
   330:         default:
   331:           System.out.println ("unknown action command " + command);
   332:         }
   333:       }
   334:     };
   335:     ButtonGroup intervalGroup = new ButtonGroup ();
   336:     smrRepeatIntervalMenu =
   337:       Multilingual.mlnText (
   338:         ComponentFactory.createMenu (
   339:           "Repeat interval",
   340:           Multilingual.mlnText (
   341:             ComponentFactory.createRadioButtonMenuItem (intervalGroup, smrRepeatInterval == -1, "Follow settings in SWITCH.X", intervalListener),
   342:             "ja", "SWITCH.X の設定に従う"),
   343:           ComponentFactory.createRadioButtonMenuItem (intervalGroup, smrRepeatInterval ==  0, (30 + 5 *  0 *  0) + "ms", intervalListener),
   344:           ComponentFactory.createRadioButtonMenuItem (intervalGroup, smrRepeatInterval ==  1, (30 + 5 *  1 *  1) + "ms", intervalListener),
   345:           ComponentFactory.createRadioButtonMenuItem (intervalGroup, smrRepeatInterval ==  2, (30 + 5 *  2 *  2) + "ms", intervalListener),
   346:           ComponentFactory.createRadioButtonMenuItem (intervalGroup, smrRepeatInterval ==  3, (30 + 5 *  3 *  3) + "ms", intervalListener),
   347:           ComponentFactory.createRadioButtonMenuItem (intervalGroup, smrRepeatInterval ==  4, (30 + 5 *  4 *  4) + "ms", intervalListener),
   348:           ComponentFactory.createRadioButtonMenuItem (intervalGroup, smrRepeatInterval ==  5, (30 + 5 *  5 *  5) + "ms", intervalListener),
   349:           ComponentFactory.createRadioButtonMenuItem (intervalGroup, smrRepeatInterval ==  6, (30 + 5 *  6 *  6) + "ms", intervalListener),
   350:           ComponentFactory.createRadioButtonMenuItem (intervalGroup, smrRepeatInterval ==  7, (30 + 5 *  7 *  7) + "ms", intervalListener),
   351:           ComponentFactory.createRadioButtonMenuItem (intervalGroup, smrRepeatInterval ==  8, (30 + 5 *  8 *  8) + "ms", intervalListener),
   352:           ComponentFactory.createRadioButtonMenuItem (intervalGroup, smrRepeatInterval ==  9, (30 + 5 *  9 *  9) + "ms", intervalListener),
   353:           ComponentFactory.createRadioButtonMenuItem (intervalGroup, smrRepeatInterval == 10, (30 + 5 * 10 * 10) + "ms", intervalListener),
   354:           ComponentFactory.createRadioButtonMenuItem (intervalGroup, smrRepeatInterval == 11, (30 + 5 * 11 * 11) + "ms", intervalListener),
   355:           ComponentFactory.createRadioButtonMenuItem (intervalGroup, smrRepeatInterval == 12, (30 + 5 * 12 * 12) + "ms", intervalListener),
   356:           ComponentFactory.createRadioButtonMenuItem (intervalGroup, smrRepeatInterval == 13, (30 + 5 * 13 * 13) + "ms", intervalListener),
   357:           ComponentFactory.createRadioButtonMenuItem (intervalGroup, smrRepeatInterval == 14, (30 + 5 * 14 * 14) + "ms", intervalListener),
   358:           ComponentFactory.createRadioButtonMenuItem (intervalGroup, smrRepeatInterval == 15, (30 + 5 * 15 * 15) + "ms", intervalListener)
   359:           ),
   360:         "ja", "リピート間隔");
   361: 
   362:     //ROMデバッガ起動フラグメニュー
   363:     ActionListener romdbListener = new ActionListener () {
   364:       @Override public void actionPerformed (ActionEvent ae) {
   365:         String command = ae.getActionCommand ();
   366:         switch (command) {
   367:         case "Follow settings in SWITCH.X":  //SWITCH.X の設定に従う
   368:           smrRomdbFlag = -1;
   369:           break;
   370:         case "OFF":
   371:           smrRomdbFlag = 0;
   372:           break;
   373:         case "AUX":
   374:           smrRomdbFlag = 255;
   375:           break;
   376:         case "CON (when using IPLROM 1.6)":  //CON (IPLROM 1.6 使用時)
   377:           smrRomdbFlag = 1;
   378:           break;
   379:         default:
   380:           System.out.println ("unknown action command " + command);
   381:         }
   382:       }
   383:     };
   384:     ButtonGroup romdbGroup = new ButtonGroup ();
   385:     smrRomdbMenu =
   386:       Multilingual.mlnText (
   387:         ComponentFactory.createMenu (
   388:           "ROM debugger start flag",
   389:           Multilingual.mlnText (
   390:             ComponentFactory.createRadioButtonMenuItem (romdbGroup, smrRomdbFlag == -1, "Follow settings in SWITCH.X", romdbListener),
   391:             "ja", "SWITCH.X の設定に従う"),
   392:           ComponentFactory.createRadioButtonMenuItem (romdbGroup, smrRomdbFlag == 0, "OFF", romdbListener),
   393:           ComponentFactory.createRadioButtonMenuItem (romdbGroup, smrRomdbFlag == 255, "AUX", romdbListener),
   394:           Multilingual.mlnText (
   395:             ComponentFactory.createRadioButtonMenuItem (romdbGroup, smrRomdbFlag == 1, "CON (when using IPLROM 1.6)", romdbListener),
   396:             "ja", "CON (IPLROM 1.6 使用時)")
   397:           ),
   398:         "ja", "ROM デバッガ起動フラグ");
   399: 
   400:     //メモリサイズ修正
   401:     smrModifyMemorySizeMenuItem =
   402:       Multilingual.mlnText (
   403:         ComponentFactory.createCheckBoxMenuItem (smrModifyMemorySizeOn, "Modify the memory size in SRAM", listener),
   404:         "ja", "SRAM にあるメモリサイズを修正する");
   405: 
   406:     //SRAMメニュー
   407:     ButtonGroup sizeGroup = new ButtonGroup ();
   408:     smrMenu =
   409:       ComponentFactory.createMenu (
   410:         "SRAM",
   411:         Multilingual.mlnText (
   412:           ComponentFactory.createMenuItem ("Zero-clear", listener),
   413:           "ja", "ゼロクリア"),
   414:         Multilingual.mlnText (
   415:           ComponentFactory.createMenuItem ("Import", listener),
   416:           "ja", "インポート"),
   417:         Multilingual.mlnText (
   418:           ComponentFactory.createMenuItem ("Export", listener),
   419:           "ja", "エクスポート"),
   420:         ComponentFactory.createHorizontalSeparator (),
   421:         Multilingual.mlnText (
   422:           ComponentFactory.createRadioButtonMenuItem (sizeGroup, smrSramSizeRequest >> 10 == 16, "16KB", listener),
   423:           "ja", "16KB"),
   424:         Multilingual.mlnText (
   425:           ComponentFactory.createRadioButtonMenuItem (sizeGroup, smrSramSizeRequest >> 10 == 32, "32KB", listener),
   426:           "ja", "32KB"),
   427:         Multilingual.mlnText (
   428:           ComponentFactory.createRadioButtonMenuItem (sizeGroup, smrSramSizeRequest >> 10 == 64, "64KB", listener),
   429:           "ja", "64KB"),
   430:         ComponentFactory.createHorizontalSeparator (),
   431:         Multilingual.mlnText (
   432:           ComponentFactory.createCheckBoxMenuItem (smrSRAMBusErrorOn, "Bus error when writing to SRAM", listener),
   433:           "ja", "SRAM への書き込み時のバスエラー")
   434:         );
   435: 
   436:     //起動デバイスメニュー
   437:     ButtonGroup bootGroup = new ButtonGroup ();
   438:     ActionListener bootListener = new ActionListener () {
   439:       @Override public void actionPerformed (ActionEvent ae) {
   440:         String command = ae.getActionCommand ();
   441:         smrParseBootDevice (
   442:           command.startsWith ("FDD ") ? "fd" + command.substring (4) :
   443:           command.startsWith ("SASI ") ? "hd" + command.substring (5) :
   444:           command.startsWith ("SCSI ") ? "sc" + command.substring (5) :
   445:           command.startsWith ("HFS ") ? "hf" + command.substring (4) :
   446:           command.equals ("STD") ? "std" :
   447:           "default");
   448:         if (smrBootDevice != -1) {  //メニューで起動デバイスが既定以外に設定されたとき
   449:           XEiJ.mpuSavedBootDevice = -1;  //保存されている起動デバイスを消す
   450:           XEiJ.mpuSavedROMBootHandle = -1;
   451:         }
   452:       }
   453:     };
   454:     JMenu bootMenuFDD = ComponentFactory.createMenu ("FDD");
   455:     for (int u = 0; u < FDC.FDC_MAX_UNITS; u++) {
   456:       bootMenuFDD.add (ComponentFactory.createRadioButtonMenuItem (
   457:         bootGroup, smrBootDevice == 0x9070 + (u << 8),
   458:         "FDD " + u, bootListener));
   459:     }
   460:     JMenu bootMenuSASI = ComponentFactory.createMenu ("SASI");
   461:     for (int u = 0; u < 16; u++) {
   462:       bootMenuSASI.add (ComponentFactory.createRadioButtonMenuItem (
   463:         bootGroup, smrBootDevice == 0x8000 + (u << 8),
   464:         "SASI " + u, bootListener));
   465:     }
   466:     JMenu bootMenuSCSI = ComponentFactory.createMenu ("SCSI");
   467:     for (int u = 0; u < 8; u++) {
   468:       bootMenuSCSI.add (ComponentFactory.createRadioButtonMenuItem (
   469:         bootGroup, smrBootDevice == 0xa000 && (smrROMBootHandle == SPC.SPC_HANDLE_EX + (u << 2) ||
   470:                                                smrROMBootHandle == SPC.SPC_HANDLE_IN + (u << 2)), "SCSI " + u, bootListener));
   471:     }
   472:     JMenu bootMenuHFS = ComponentFactory.createMenu ("HFS");
   473:     for (int u = 0; u < HFS.HFS_MAX_UNITS; u++) {
   474:       bootMenuHFS.add (ComponentFactory.createRadioButtonMenuItem (
   475:         bootGroup, smrBootDevice == 0xa000 && smrROMBootHandle == HFS.HFS_BOOT_HANDLE && HFS.hfsBootUnit == u,
   476:         "HFS " + u, bootListener));
   477:     }
   478:     smrBootMenu =
   479:       Multilingual.mlnText (
   480:         ComponentFactory.createMenu (
   481:           "Boot device",
   482:           Multilingual.mlnText (
   483:             ComponentFactory.createRadioButtonMenuItem (bootGroup, smrBootDevice == -1, "Follow settings in SWITCH.X", bootListener),
   484:             "ja", "SWITCH.X の設定に従う"),
   485:           smrSTDMenuItem = ComponentFactory.createRadioButtonMenuItem (bootGroup, smrBootDevice == 0x0000, "STD", bootListener),
   486:           bootMenuFDD,
   487:           bootMenuSASI,
   488:           bootMenuSCSI,
   489:           bootMenuHFS
   490:           ),
   491:         "ja", "起動デバイス");
   492: 
   493:   }  //smrInit()
   494: 
   495:   //smrParseBootDevice ()
   496:   //  起動デバイスの設定を読み取る
   497:   public static void smrParseBootDevice (String boot) {
   498:     smrBootDevice = -1;  //起動デバイス
   499:     smrROMBootHandle = -1;  //ROM起動ハンドル
   500:     smrRAMBootAddress = -1;  //RAM起動アドレス
   501:     boot = boot.toLowerCase ();
   502:     if (boot.equals ("std")) {  //std
   503:       smrBootDevice = 0x0000;  //STD 起動
   504:     } else if (boot.startsWith ("fd")) {  //fdN
   505:       int u = XEiJ.fmtParseInt (boot, 2, 0, FDC.FDC_MAX_UNITS - 1, FDC.FDC_MAX_UNITS);  //起動ユニット番号
   506:       if (u < FDC.FDC_MAX_UNITS) {
   507:         smrBootDevice = 0x9070 + (u << 8);  //FDD起動
   508:       }
   509:     } else if (boot.startsWith ("hd")) {  //hdN
   510:       int u = XEiJ.fmtParseInt (boot, 2, 0, 15, 16);  //起動ユニット番号
   511:       if (u < 16) {
   512:         smrBootDevice = 0x8000 + (u << 8);  //SASI起動
   513:       }
   514:     } else if (boot.startsWith ("sc")) {  //scN
   515:       int u = XEiJ.fmtParseInt (boot, 2, 0, 7, 8);
   516:       if (u < 8) {
   517:         smrBootDevice = 0xa000;  //ROM起動
   518:         smrROMBootHandle = SPC.SPC_HANDLE_EX + ((u & 7) << 2);  //仮に拡張SCSI起動にしておく。リセットしたとき拡張SCSIがなければ内蔵SCSIに読み替えられる
   519:       }
   520:     } else if (boot.startsWith ("hf")) {  //hfN
   521:       int u = XEiJ.fmtParseInt (boot, 2, 0, HFS.HFS_MAX_UNITS - 1, HFS.HFS_MAX_UNITS);  //起動ユニット番号
   522:       if (u < HFS.HFS_MAX_UNITS) {
   523:         HFS.hfsBootUnit = u;
   524:         smrBootDevice = 0xa000;  //ROM起動
   525:         smrROMBootHandle = HFS.HFS_BOOT_HANDLE;  //IPL起動ハンドル
   526:       }
   527:     } else if (boot.startsWith ("rom$")) {  //rom$X
   528:       int handle = XEiJ.fmtParseIntRadix (boot, 3, 0, 0x00ffffff, 0x01000000, 16);  //起動ハンドル
   529:       if (handle < 0x01000000) {
   530:         smrBootDevice = 0xa000;  //ROM起動
   531:         smrROMBootHandle = handle;
   532:       }
   533:     } else if (boot.startsWith ("ram$")) {  //ram$X
   534:       int handle = XEiJ.fmtParseIntRadix (boot, 3, 0, 0x00ffffff, 0x01000000, 16);  //起動ハンドル
   535:       if (handle < 0x01000000) {
   536:         smrBootDevice = 0xb000;  //RAM起動
   537:         smrRAMBootAddress = handle;
   538:       }
   539:     }
   540:   }  //smrParseBootDevice(String)
   541: 
   542:   //smrReset ()
   543:   //  SRAMリセット
   544:   //  ここでROMも上書きする
   545:   //  ROMを初期化してから呼び出すこと
   546:   //  SPC.spcReset()よりも後であること
   547:   public static void smrReset () {
   548:     smrWriteEnableOn = false;
   549: 
   550:     //SRAMの容量を変更する
   551:     {
   552:       smrSramCurrentSize = smrSramSizeRequest;
   553:       XEiJ.busSuper (MemoryMappedDevice.MMD_SMR, 0x00ed0000, 0x00ed0000 + smrSramSizeRequest);  //SMR SRAM
   554:       if (smrSramSizeRequest < 65536) {
   555:         XEiJ.busSuper (MemoryMappedDevice.MMD_NUL, 0x00ed0000 + smrSramSizeRequest, 0x00ed0000 + 65536);  //空き
   556:       }
   557:       System.out.printf (Multilingual.mlnJapanese ?
   558:                          "SRAM の容量は %dKB ($%08X-$%08X) です\n" :
   559:                          "Capacity of SRAM is %dKB ($%08X-$%08X)\n",
   560:                          smrSramCurrentSize >> 10, 0x00ed0000, 0x00ed0000 + smrSramCurrentSize - 1);
   561:     }
   562: 
   563:     //ROM起動ハンドルを調整する
   564:     //  ROM起動ハンドルが内蔵SCSIを指しているが内蔵SCSIがないとき
   565:     //    拡張SCSIがあるとき
   566:     //      ROM起動ハンドルを拡張SCSIにする
   567:     //    拡張SCSIがないとき
   568:     //      ROM起動ハンドルを消す
   569:     //      ROM起動のとき
   570:     //        STD起動にする
   571:     //  ROM起動ハンドルが拡張SCSIを指しているが拡張SCSIがないとき
   572:     //    内蔵SCSIがあるとき
   573:     //      ROM起動ハンドルを内蔵SCSIにする
   574:     //    内蔵SCSIがないとき
   575:     //      ROM起動ハンドルを消す
   576:     //      ROM起動のとき
   577:     //        STD起動にする
   578:     //  ROM起動ハンドルがHFSを指しているがHFSのディレクトリが設定されていないとき
   579:     //    ROM起動ハンドルを消す
   580:     //    ROM起動のとき
   581:     //      STD起動にする
   582:     //起動デバイス
   583:     if ((smrROMBootHandle & ~(7 << 2)) == SPC.SPC_HANDLE_IN && !SPC.spcSCSIINOn) {  //ROM起動ハンドルが内蔵SCSIを指しているが内蔵SCSIがないとき
   584:       if (SPC.spcSCSIEXOn) {  //拡張SCSIがあるとき
   585:         smrROMBootHandle = SPC.SPC_HANDLE_EX + (smrROMBootHandle & (7 << 2));  //ROM起動ハンドルを拡張SCSIにする
   586:         //MainMemory.mmrWb (0x00ed0070, MainMemory.mmrRbs (0x00ed0070) | 0x08);  //拡張フラグをセットする
   587:       } else {  //拡張SCSIがないとき
   588:         smrROMBootHandle = 0x00e80400;  //ROM起動ハンドルを消す
   589:         if (smrBootDevice == 0xa000) {  //ROM起動のとき
   590:           smrBootDevice = 0x0000;  //STD起動にする
   591:           smrSTDMenuItem.setSelected (true);
   592:         }
   593:       }
   594:     }
   595:     if ((smrROMBootHandle & ~(7 << 2)) == SPC.SPC_HANDLE_EX && !SPC.spcSCSIEXOn) {  //ROM起動ハンドルが拡張SCSIを指しているが拡張SCSIがないとき
   596:       if (SPC.spcSCSIINOn) {  //内蔵SCSIがあるとき
   597:         smrROMBootHandle = SPC.SPC_HANDLE_IN + (smrROMBootHandle & (7 << 2));  //ROM起動ハンドルを内蔵SCSIにする
   598:         //MainMemory.mmrWb (0x00ed0070, MainMemory.mmrRbs (0x00ed0070) & ~0x08);  //拡張フラグをクリアする
   599:       } else {  //内蔵SCSIがないとき
   600:         smrROMBootHandle = 0x00e80400;  //ROM起動ハンドルを消す
   601:         if (smrBootDevice == 0xa000) {  //ROM起動のとき
   602:           smrBootDevice = 0x0000;  //STD起動にする
   603:           smrSTDMenuItem.setSelected (true);
   604:         }
   605:       }
   606:     }
   607:     if (smrROMBootHandle == HFS.HFS_BOOT_HANDLE &&  //ROM起動ハンドルがHFSを指しているが
   608:         (!HFS.hfsUnitArray[HFS.hfsBootUnit].abuConnected ||
   609:          !HFS.hfsUnitArray[HFS.hfsBootUnit].abuInserted)) {  //HFSのディレクトリが設定されていないとき
   610:       smrROMBootHandle = 0x00e80400;  //ROM起動ハンドルを消す
   611:       if (smrBootDevice == 0xa000) {  //ROM起動のとき
   612:         smrBootDevice = 0x0000;  //STD起動にする
   613:         smrSTDMenuItem.setSelected (true);
   614:       }
   615:     }
   616:     //ここから再起動
   617:     if ((XEiJ.mpuROMBootHandle & ~(7 << 2)) == SPC.SPC_HANDLE_IN && !SPC.spcSCSIINOn) {  //ROM起動ハンドルが内蔵SCSIを指しているが内蔵SCSIがないとき
   618:       if (SPC.spcSCSIEXOn) {  //拡張SCSIがあるとき
   619:         XEiJ.mpuROMBootHandle = SPC.SPC_HANDLE_EX + (XEiJ.mpuROMBootHandle & (7 << 2));  //ROM起動ハンドルを拡張SCSIにする
   620:         //MainMemory.mmrWb (0x00ed0070, MainMemory.mmrRbs (0x00ed0070) | 0x08);  //拡張フラグをセットする
   621:       } else {  //拡張SCSIがないとき
   622:         XEiJ.mpuROMBootHandle = 0x00e80400;  //ROM起動ハンドルを消す
   623:         if (XEiJ.mpuBootDevice == 0xa000) {  //ROM起動のとき
   624:           XEiJ.mpuBootDevice = 0x0000;  //STD起動にする
   625:         }
   626:       }
   627:     }
   628:     if ((XEiJ.mpuROMBootHandle & ~(7 << 2)) == SPC.SPC_HANDLE_EX && !SPC.spcSCSIEXOn) {  //ROM起動ハンドルが拡張SCSIを指しているが拡張SCSIがないとき
   629:       if (SPC.spcSCSIINOn) {  //内蔵SCSIがあるとき
   630:         XEiJ.mpuROMBootHandle = SPC.SPC_HANDLE_IN + (XEiJ.mpuROMBootHandle & (7 << 2));  //ROM起動ハンドルを内蔵SCSIにする
   631:         //MainMemory.mmrWb (0x00ed0070, MainMemory.mmrRbs (0x00ed0070) & ~0x08);  //拡張フラグをクリアする
   632:       } else {  //内蔵SCSIがないとき
   633:         XEiJ.mpuROMBootHandle = 0x00e80400;  //ROM起動ハンドルを消す
   634:         if (XEiJ.mpuBootDevice == 0xa000) {  //ROM起動のとき
   635:           XEiJ.mpuBootDevice = 0x0000;  //STD起動にする
   636:         }
   637:       }
   638:     }
   639:     if (XEiJ.mpuROMBootHandle == HFS.HFS_BOOT_HANDLE &&  //ROM起動ハンドルがHFSを指しているが
   640:         (!HFS.hfsUnitArray[HFS.hfsBootUnit].abuConnected ||
   641:          !HFS.hfsUnitArray[HFS.hfsBootUnit].abuInserted)) {  //HFSのディレクトリが設定されていないとき
   642:       XEiJ.mpuROMBootHandle = 0x00e80400;  //ROM起動ハンドルを消す
   643:       if (XEiJ.mpuBootDevice == 0xa000) {  //ROM起動のとき
   644:         XEiJ.mpuBootDevice = 0x0000;  //STD起動にする
   645:       }
   646:     }
   647: 
   648:     smrOverride ();
   649: 
   650:   }  //smrReset()
   651: 
   652:   //smrOverride ()
   653:   //  SRAMの設定を上書きする
   654:   //  ここから再起動もSRAMに上書きする
   655:   public static void smrOverride () {
   656:     if (MainMemory.mmrRls (0x00ed0000) == 0x82773638 &&  //X68
   657:         MainMemory.mmrRls (0x00ed0004) == 0x30303057) {  //000W  初期化されている。初期化されていないときに上書きしても意味がない
   658:       //メモリサイズ
   659:       if (smrModifyMemorySizeOn) {
   660:         int memorySizeAddress = 0x00ed0008;
   661:         int memorySizeOld = MainMemory.mmrRls (memorySizeAddress);
   662:         int memorySizeNew = MainMemory.mmrMemorySizeCurrent;
   663:         if (memorySizeOld != memorySizeNew) {
   664:           MainMemory.mmrWl (memorySizeAddress, memorySizeNew);
   665:           System.out.printf (Multilingual.mlnJapanese ?
   666:                              "SRAM にあるメモリサイズを %dMB から %dMB に変更しました\n" :
   667:                              "Changed the memory size in SRAM from %dMB to %dMB\n",
   668:                              memorySizeOld >> 20,
   669:                              memorySizeNew >> 20);
   670:         }
   671:       }
   672:       //ROM起動ハンドル
   673:       int romHandleAddress = 0x00ed000c;
   674:       int romHandleOld = MainMemory.mmrRls (romHandleAddress);
   675:       int romHandleNew = XEiJ.mpuROMBootHandle != -1 ? XEiJ.mpuROMBootHandle : smrROMBootHandle;
   676:       if (romHandleNew != -1 &&
   677:           romHandleOld != romHandleNew) {
   678:         MainMemory.mmrWl (romHandleAddress, romHandleNew);
   679:         System.out.printf (Multilingual.mlnJapanese ?
   680:                            "SRAM にある ROM 起動ハンドルを $%08X から $%08X に変更しました\n" :
   681:                            "Changed the ROM boot handle in SRAM from $%08X to $%08X\n",
   682:                            romHandleOld,
   683:                            romHandleNew);
   684:       }
   685:       //RAM起動アドレス
   686:       int ramAddressAddress = 0x00ed0010;
   687:       int ramAddressOld = MainMemory.mmrRls (ramAddressAddress);
   688:       int ramAddressNew = smrRAMBootAddress;
   689:       if (ramAddressNew != -1 &&
   690:           ramAddressOld != ramAddressNew) {
   691:         MainMemory.mmrWl (ramAddressAddress, ramAddressNew);
   692:         System.out.printf (Multilingual.mlnJapanese ?
   693:                            "SRAM にある RAM 起動アドレスを $%08X から $%08X に変更しました\n" :
   694:                            "Changed the RAM boot address in SRAM from $%08X to $%08X\n",
   695:                            ramAddressOld,
   696:                            ramAddressNew);
   697:       }
   698:       //起動デバイス
   699:       int deviceAddress = 0x00ed0018;
   700:       int deviceOld = MainMemory.mmrRwz (deviceAddress);
   701:       int deviceNew = XEiJ.mpuBootDevice != -1 ? XEiJ.mpuBootDevice : smrBootDevice;
   702:       if (deviceNew != -1 &&
   703:           deviceOld != deviceNew) {
   704:         MainMemory.mmrWw (deviceAddress, deviceNew);
   705:         System.out.printf (Multilingual.mlnJapanese ?
   706:                            "SRAM にある起動デバイスを %s から %s に変更しました\n" :
   707:                            "Changed the boot device in SRAM from %s to %s\n",
   708:                            smrBootDescription (romHandleOld, ramAddressOld, deviceOld),
   709:                            smrBootDescription (romHandleNew, ramAddressNew, deviceNew));
   710:       }
   711:       //リピート開始
   712:       int repeatDelayAddress = 0x00ed003a;
   713:       int repeatDelayOld = MainMemory.mmrRbz (repeatDelayAddress);
   714:       int repeatDelayNew = smrRepeatDelay;
   715:       if (repeatDelayNew != -1 &&
   716:           repeatDelayOld != repeatDelayNew) {
   717:         MainMemory.mmrWb (repeatDelayAddress, repeatDelayNew);
   718:         System.out.printf (Multilingual.mlnJapanese ?
   719:                            "SRAM にあるリピート開始を %dms から %dms に変更しました\n" :
   720:                            "Changed the repeat delay in SRAM from %dms to %dms\n",
   721:                            200 + 100 * (repeatDelayOld & 15),
   722:                            200 + 100 * (repeatDelayNew & 15));
   723:       }
   724:       //リピート間隔
   725:       int repeatIntervalAddress = 0x00ed003b;
   726:       int repeatIntervalOld = MainMemory.mmrRbz (repeatIntervalAddress);
   727:       int repeatIntervalNew = smrRepeatInterval;
   728:       if (repeatIntervalNew != -1 &&
   729:           repeatIntervalOld != repeatIntervalNew) {
   730:         MainMemory.mmrWb (repeatIntervalAddress, repeatIntervalNew);
   731:         System.out.printf (Multilingual.mlnJapanese ?
   732:                            "SRAM にあるリピート間隔を %dms から %dms に変更しました\n" :
   733:                            "Changed the repeat interval in SRAM from %dms to %dms\n",
   734:                            30 + 5 * (repeatDelayOld & 15),
   735:                            30 + 5 * (repeatDelayNew & 15));
   736:       }
   737:       //ROMデバッガ起動フラグ
   738:       if (smrRomdbFlag != -1) {  //設定する
   739:         boolean iplrom16 = (XEiJ.currentAccelerator == XEiJ.ACCELERATOR_HYBRID ||
   740:                             XEiJ.currentAccelerator == XEiJ.ACCELERATOR_060TURBO ||
   741:                             XEiJ.currentAccelerator == XEiJ.ACCELERATOR_060TURBOPRO ||
   742:                             ROM.romIPLROM16On);  //IPLROM 1.6か
   743:         boolean nonexistence = (XEiJ.currentModel.getIPLROM () == 130 && !iplrom16 &&
   744:                                 ROM.romROM30Data == null);  //ROMデバッガがないか。IPLROM 1.3でROM30.DATが指定されていない
   745:         int address = 0x00ed0058;
   746:         int oldData = MainMemory.mmrRbz (address);
   747:         int newData = (nonexistence ? 0 :  //ROMデバッガがないときOFF
   748:                        !iplrom16 && smrRomdbFlag == 1 ? 255 :  //IPLROM 1.6でないときCONをAUXに変更
   749:                        smrRomdbFlag);
   750:         if (oldData != newData) {
   751:           MainMemory.mmrWb (address, newData);
   752:           System.out.printf (Multilingual.mlnJapanese ?
   753:                              "SRAM にある ROM デバッガ起動フラグを %s から %s に変更しました\n" :
   754:                              "ROM debugger startup flag in SRAM changed from %s to %s\n",
   755:                              oldData == 0 ? "OFF" : oldData == 255 ? "AUX" : "CON",
   756:                              newData == 0 ? "OFF" : newData == 255 ? "AUX" : "CON");
   757:         }
   758:       }
   759:       //SASIハードディスクの最大数
   760:       int hdMaxAddress = 0x00ed005a;
   761:       int hdMaxOld = MainMemory.mmrRbz (hdMaxAddress);
   762:       int sasiFlag = MainMemory.mmrRbz (0x00ed006f) == 'V' ? MainMemory.mmrRbz (0x00ed0071) : 0;
   763:       int hdMaxNew = SPC.spcSCSIINOn ? 2 * (32 - Integer.numberOfLeadingZeros (sasiFlag)) : HDC.hdcHDMax;
   764:       if (hdMaxOld != hdMaxNew) {
   765:         MainMemory.mmrWb (hdMaxAddress, hdMaxNew);
   766:         System.out.printf (Multilingual.mlnJapanese ?
   767:                            "SRAM にある SASI ハードディスクの最大数を %d から %d に変更しました\n" :
   768:                            "Changed the maximum number of SASI hard disks in SRAM from %d to %d\n",
   769:                            hdMaxOld, hdMaxNew);
   770:       }
   771:     }
   772:     //「ここから再起動」をキャンセルする
   773:     //XEiJ.mpuBootDevice = -1;
   774:     //XEiJ.mpuROMBootHandle = -1;
   775:   }
   776: 
   777:   //s = smrBootDescription (code, romHandle, ramAddress)
   778:   //  device      $00ED0018  起動デバイス
   779:   //                           $0000  STD  FD→HD→ROM→RAM
   780:   //                           $8xxx  HD
   781:   //                           $9xxx  FD
   782:   //                           $Axxx  ROM  ROM起動ハンドルからROM起動アドレスを取り出して呼び出す
   783:   //                                       ROM起動ハンドルがバスエラーになるときはSTDで起動する
   784:   //                           $Bxxx  RAM  RAM起動アドレスを呼び出す。先頭が$60でなければならない
   785:   //  romHandle   $00ED000C  ROM起動ハンドル
   786:   //  ramAddress  $00ED0010  RAM起動アドレス
   787:   public static String smrBootDescription (int romHandle, int ramAddress, int device) {
   788:     switch (device & 0xf000) {
   789:     case 0x8000:
   790:       return "HD" + (device >> 8 & 15);
   791:     case 0x9000:
   792:       return "2HD" + (device >> 8 & 3);
   793:     case 0xa000:
   794:       return ((romHandle & ~(7 << 2)) == SPC.SPC_HANDLE_IN ? "SCSI" + ((romHandle >> 2) & 7) :   //内蔵SCSI
   795:               (romHandle & ~(7 << 2)) == SPC.SPC_HANDLE_EX ? "SCSI" + ((romHandle >> 2) & 7) :   //拡張SCSI
   796:               "ROM$" + XEiJ.fmtHex6 (romHandle));
   797:     case 0xb000:
   798:       return "RAM$" + XEiJ.fmtHex6 (ramAddress);
   799:     default:
   800:       return "STD";
   801:     }
   802:   }
   803: 
   804:   //smrClear ()
   805:   //  SRAMクリア
   806:   public static void smrClear () {
   807:     XEiJ.pnlExitFullScreen (true);
   808:     if (JOptionPane.showConfirmDialog (
   809:       XEiJ.frmFrame,
   810:       Multilingual.mlnJapanese ? "SRAM をクリアしますか?" : "Do you want to clear SRAM?",
   811:       Multilingual.mlnJapanese ? "確認" : "Confirmation",
   812:       JOptionPane.YES_NO_OPTION,
   813:       JOptionPane.PLAIN_MESSAGE) == JOptionPane.YES_OPTION) {
   814:       Arrays.fill (MainMemory.mmrM8, 0x00ed0000, 0x00ed0000 + 65536, (byte) 0x00);
   815:     }
   816:   }  //smrClear()
   817: 
   818:   //smrLoad ()
   819:   //  SRAM読み込み
   820:   public static void smrLoad () {
   821:     JFileChooser2 fileChooser = new JFileChooser2 ();
   822:     fileChooser.setFileFilter (new javax.swing.filechooser.FileFilter () {  //java.io.FileFilterと紛らわしい
   823:       @Override public boolean accept (File file) {
   824:         String name = file.getName ();
   825:         String upperName = name.toUpperCase ();
   826:         return (file.isDirectory () ||
   827:                 (file.isFile () &&
   828:                  upperName.startsWith ("SRAM")));
   829:       }
   830:       @Override public String getDescription () {
   831:         return (Multilingual.mlnJapanese ?
   832:                 "SRAM データファイル (SRAM*.*)" :
   833:                 "SRAM data files (SRAM*.*)");
   834:       }
   835:     });
   836:     if (fileChooser.showOpenDialog (null) == JFileChooser.APPROVE_OPTION) {
   837:       File file = fileChooser.getSelectedFile ();
   838:       String name = file.getPath ();
   839:       if (!smrLoadData (name)) {  //読み込めなかった
   840:         XEiJ.pnlExitFullScreen (true);
   841:         JOptionPane.showMessageDialog (null,
   842:                                        Multilingual.mlnJapanese ?
   843:                                        name + " のサイズが違います" :
   844:                                        name + " has wrong size");
   845:         return;
   846:       }
   847:     }
   848:   }  //smrLoad()
   849: 
   850:   //success = smrLoadData (name)
   851:   //  SRAMのイメージファイルを読み込む
   852:   public static boolean smrLoadData (String name) {
   853:     byte[] array = XEiJ.rscGetFile (name, smrSramSizeRequest);
   854:     if (array != null) {  //読み込めた
   855:       System.arraycopy (array, 0, MainMemory.mmrM8, 0x00ed0000, smrSramSizeRequest);  //SRAMにコピーする
   856:       if (smrSramSizeRequest < 65536) {
   857:         Arrays.fill (MainMemory.mmrM8, 0x00ed0000 + smrSramSizeRequest, 0x00ed0000 + 65536, (byte) 0x00);  //空き
   858:       }
   859:       return true;
   860:     }
   861:     return false;
   862:   }
   863: 
   864:   //smrSave ()
   865:   //  SRAM書き出し
   866:   public static void smrSave () {
   867:     JFileChooser2 fileChooser = new JFileChooser2 ();
   868:     fileChooser.setFileFilter (new javax.swing.filechooser.FileFilter () {  //java.io.FileFilterと紛らわしい
   869:       @Override public boolean accept (File file) {
   870:         String name = file.getName ();
   871:         String upperName = name.toUpperCase ();
   872:         return (file.isDirectory () ||
   873:                 (file.isFile () &&
   874:                  upperName.startsWith ("SRAM")));
   875:       }
   876:       @Override public String getDescription () {
   877:         return (Multilingual.mlnJapanese ?
   878:                 "SRAM データファイル (SRAM*.*)" :
   879:                 "SRAM data files (SRAM*.*)");
   880:       }
   881:     });
   882:     if (fileChooser.showSaveDialog (null) == JFileChooser.APPROVE_OPTION) {
   883:       XEiJ.rscPutFile (fileChooser.getSelectedFile ().getPath (), MainMemory.mmrM8, 0x00ed0000, smrSramSizeRequest);
   884:     }
   885:   }  //smrSave()
   886: 
   887: }  //class SRAM