XEiJ.java
     1: //========================================================================================
     2: //  XEiJ.java
     3: //    en:Main class
     4: //    ja:メインクラス
     5: //  Copyright (C) 2003-2024 Makoto Kamada
     6: //
     7: //  This file is part of the XEiJ (X68000 Emulator in Java).
     8: //  You can use, modify and redistribute the XEiJ if the conditions are met.
     9: //  Read the XEiJ License for more details.
    10: //  https://stdkmd.net/xeij/
    11: //========================================================================================
    12: 
    13: package xeij;
    14: 
    15: import java.awt.*;  //BasicStroke,BorderLayout,BoxLayout,Color,Component,Container,Cursor,Desktop,Dimension,Font,FlowLayout,Frame,Graphics,Graphics2D,GraphicsDevice,GraphicsEnvironment,GridLayout,Image,Insets,Paint,Point,Rectangle,RenderingHints,Robot,Shape,Stroke,TexturePaint,Toolkit
    16: import java.awt.datatransfer.*;  //Clipboard,DataFlavor,FlavorEvent,FlavorListener,Transferable,UnsupportedFlavorException
    17: import java.awt.dnd.*;  //DnDConstants,DropTarget,DropTargetAdapter,DropTargetDragEvent
    18: import java.awt.event.*;  //ActionEvent,ActionListener,ComponentAdapter,ComponentEvent,ComponentListener,FocusAdapter,FocusEvent,FocusListener,InputEvent,KeyAdapter,KeyEvent,KeyListener,MouseAdapter,MouseEvent,MouseListener,MouseMotionAdapter,MouseWheelEvent,WindowAdapter,WindowEvent,WindowListener,WindowStateListener
    19: import java.awt.font.*;  //FontRenderContext,LineMetrics,TextLayout
    20: import java.awt.geom.*;  //AffineTransform,GeneralPath,Point2D,Rectangle2D
    21: import java.awt.image.*;  //BufferedImage,DataBuffer,DataBufferByte,DataBufferInt,IndexColorModel
    22: import java.io.*;  //BufferedInputStream,BufferedOutputStream,BufferedReader,BufferedWriter,ByteArrayOutputStream,File,FileInputStream,FileNotFoundException,FileReader,InputStream,InputStreamReader,IOException,OutputStreamWriter,RandomAccessFile,UnsupportedEncodingException
    23: import java.lang.*;  //Boolean,Character,Class,Comparable,Double,Exception,Float,IllegalArgumentException,Integer,InterruptedException,Long,Math,Number,Object,Runnable,SecurityException,String,StringBuilder,System
    24: import java.math.*;  //BigDecimal,BigInteger,MathContext,RoundingMode
    25: import java.net.*;  //MalformedURLException,URI,URL
    26: import java.nio.*;  //ByteBuffer,ByteOrder
    27: import java.nio.charset.*;  //Charset
    28: import java.util.*;  //ArrayList,Arrays,Calendar,GregorianCalendar,HashMap,Map,Map.Entry,LinkedList,TimeZone,Timer,TimerTask,TreeMap
    29: import java.util.function.*;  //IntConsumer,IntSupplier
    30: import java.util.regex.*;  //Matcher,Pattern
    31: import java.util.zip.*;  //CRC32,Deflater,GZIPInputStream,GZIPOutputStream,ZipEntry,ZipInputStream
    32: import javax.imageio.*;  //ImageIO
    33: import javax.imageio.stream.*;  //ImageOutputStream
    34: import javax.swing.*;  //AbstractButton,AbstractSpinnerModel,Box,ButtonGroup,DefaultListModel,ImageIcon,JButton,JCheckBox,JCheckBoxMenuItem,JComponent,JDialog,JFileChooser,JFrame,JLabel,JList,JMenu,JMenuBar,JMenuItem,JPanel,JRadioButton,JScrollPane,JSpinner,JTextArea,JTextField,JTextPane,JViewport,ScrollPaneConstants,SpinnerListModel,SpinnerNumberModel,SwingConstants,SwingUtilities,UIManager,UIDefaults,UnsupportedLookAndFeelException
    35: import javax.swing.event.*;  //CaretEvent,CaretListener,ChangeEvent,ChangeListener,DocumentEvent,DocumentListener,ListSelectionListener
    36: import javax.swing.text.*;  //AbstractDocument,BadLocationException,DefaultCaret,Document,DocumentFilter,JTextComponent,ParagraphView,Style,StyleConstants,StyleContext,StyledDocument
    37: 
    38: public class XEiJ {
    39: 
    40:   //名前とバージョン
    41:   public static final String PRG_TITLE = "XEiJ (X68000 Emulator in Java)";  //タイトル
    42:   public static final String PRG_VERSION = "0.24.11.08";  //バージョン
    43:   public static final String PRG_AUTHOR = "Makoto Kamada";  //作者
    44:   public static final String PRG_WEBPAGE = "https://stdkmd.net/xeij/";  //ウェブページ
    45: 
    46:   public static final String PRG_JAVA_VENDOR = "Oracle Corporation";  //動作を確認しているJavaのベンダー
    47:   public static final String PRG_JAVA_VERSION = "23.0.1";  //動作を確認しているJavaのバージョン
    48:   public static final String PRG_OS_ARCH = "amd64";  //動作を確認しているOSのアーキテクチャ
    49:   public static final String PRG_OS_NAME = "Windows 10";  //動作を確認しているOSの名前
    50: 
    51:   public static final String PRG_WINDLL_NAME = "xeijwin";  //DLLの名前。".dll"を含まない
    52:   public static final int PRG_WINDLL_VERSION = 20231008;  //DLLのバージョン
    53: 
    54:   //全体の設定
    55:   //  bit0..3のテストにシフトを使う
    56:   //    TEST_BIT_0_SHIFT ? a << 31 != 0 : (a & 1) != 0
    57:   //    TEST_BIT_1_SHIFT ? a << 30 < 0 : (a & 2) != 0
    58:   //    TEST_BIT_2_SHIFT ? a << 29 < 0 : (a & 4) != 0
    59:   //    TEST_BIT_3_SHIFT ? a << 28 < 0 : (a & 8) != 0
    60:   public static final boolean TEST_BIT_0_SHIFT = false;  //true=bit0のテストにシフトを使う
    61:   public static final boolean TEST_BIT_1_SHIFT = false;  //true=bit1のテストにシフトを使う
    62:   public static final boolean TEST_BIT_2_SHIFT = true;  //true=bit2のテストにシフトを使う
    63:   public static final boolean TEST_BIT_3_SHIFT = true;  //true=bit3のテストにシフトを使う
    64:   //  shortの飽和処理にキャストを使う
    65:   //    x = SHORT_SATURATION_CAST ? (short) x == x ? x : x >> 31 ^ 32767 : Math.max (-32768, Math.min (32767, x));
    66:   //    m = SHORT_SATURATION_CAST ? (short) m == m ? m : m >> 31 ^ 32767 : Math.max (-32768, Math.min (32767, m));
    67:   //    l = SHORT_SATURATION_CAST ? (short) l == l ? l : l >> 31 ^ 32767 : Math.max (-32768, Math.min (32767, l));
    68:   //    r = SHORT_SATURATION_CAST ? (short) r == r ? r : r >> 31 ^ 32767 : Math.max (-32768, Math.min (32767, r));
    69:   //  または
    70:   //    if (SHORT_SATURATION_CAST) {
    71:   //      if ((short) x != x) {
    72:   //        x = x >> 31 ^ 32767;
    73:   //      }
    74:   //    } else {
    75:   //      if (x < -32768) {
    76:   //        x = -32768;
    77:   //      } else if (x > 32767) {
    78:   //        x = 32767;
    79:   //      }
    80:   //    }
    81:   public static final boolean SHORT_SATURATION_CAST = false;  //shortの飽和処理にキャストを使う
    82: 
    83:   //バイナリデータの埋め込み
    84:   //  byte[]の場合
    85:   //    Javaはbyteの定数配列をstatic final byte[] XXX={~}で直接記述しにくい
    86:   //      bit7がセットされているデータをいちいち(byte)でキャストしなければならない
    87:   //      初期化コードが巨大化してコンパイラを通らなくなる
    88:   //    Stringに詰め込んで起動時にString.getBytes(Charset)を使ってbyte[]に展開する
    89:   //    ISO-8859-1はすべてのJava実行環境で実装しなければならないことになっているので環境依存にはならない
    90:   //    static final int[] XXX={~}で書いておいてPerlスクリプトで文字列に変換する
    91:   //    final int[]をbyte[]に変更すると動作が遅くなる場合があることに注意する
    92:   //    perl misc/itob.pl xeij/???.java XXX
    93:   public static final Charset ISO_8859_1 = Charset.forName ("ISO-8859-1");
    94:   static {
    95:     if (false) {
    96:       //ISO-8859-1が8bitバイナリデータを素通りさせるかどうかのテスト
    97:       StringBuilder sb = new StringBuilder ();
    98:       for (int i = 0; i < 256; i++) {
    99:         sb.append ((char) i);
   100:       }
   101:       byte[] bb = sb.toString ().getBytes (ISO_8859_1);
   102:       for (int i = 0; i < 256; i++) {
   103:         System.out.printf ("%02x %02x %s\n", i, bb[i] & 255, i == (bb[i] & 255) ? "OK" : "ERROR");
   104:       }
   105:     }
   106:   }
   107:   //  char[]の場合
   108:   //    byte[]の場合と同様にStringに詰め込んで起動時にString.toCharArray()を使ってchar[]に展開する
   109:   //    static final int[] XXX={~}で書いておいてPerlスクリプトで文字列に変換する
   110:   //    final int[]をchar[]に変更すると動作が遅くなる場合があることに注意する
   111:   //    perl misc/itoc.pl xeij/???.java XXX
   112: 
   113: 
   114: 
   115:   //========================================================================================
   116:   //$$PRG プログラムの入り口と出口
   117: 
   118:   //動作環境
   119:   public static String prgJavaVendor;  //動作環境のJavaのベンダー
   120:   public static String prgJavaVersion;  //動作環境のJavaのバージョン
   121:   public static String prgOsArch;  //動作環境のアーキテクチャ
   122:   public static String prgOsName;  //OSの名前
   123:   public static boolean prgIsLinux;  //true=Linux
   124:   public static boolean prgIsMac;  //true=Mac
   125:   public static boolean prgIsWindows;  //true=Windows
   126:   public static boolean prgWindllLoaded;  //true=DLLを読み込んだ
   127: 
   128:   public static boolean prgCaseIgnored;  //true=ファイル名の大文字と小文字が区別されない
   129: 
   130:   public static boolean prgVerbose;
   131: 
   132:   public static String[] prgArgs;
   133: 
   134:   //main (args)
   135:   //  開始
   136:   public static void main (String[] args) {
   137: 
   138:     prgArgs = args;
   139: 
   140:     //起動する
   141:     SwingUtilities.invokeLater (new Runnable () {
   142:       @Override public void run () {
   143:         new XEiJ ();
   144:       }
   145:     });
   146: 
   147:   }  //main(String[])
   148: 
   149:   //XEiJ ()
   150:   //  コンストラクタ
   151:   public XEiJ () {
   152: 
   153:     prgJavaVendor = System.getProperty ("java.vendor");
   154:     prgJavaVersion = System.getProperty ("java.version");
   155:     prgOsArch = System.getProperty ("os.arch");
   156:     prgOsName = System.getProperty ("os.name");
   157:     prgIsLinux = 0 <= prgOsName.indexOf ("Linux");
   158:     prgIsMac = 0 <= prgOsName.indexOf ("Mac");
   159:     prgIsWindows = 0 <= prgOsName.indexOf ("Windows");
   160: 
   161:     System.out.print ("\n" +
   162:                       "-------------------------------------------------\n" +
   163:                       PRG_TITLE + " version " + PRG_VERSION + "\n" +
   164:                       "-------------------------------------------------\n");
   165: 
   166:     //初期化
   167:     //  この段階でコンポーネントを参照してはならない
   168:     //  メニューの初期値に必要な情報があればここで作っておく
   169:     prgCaseIgnored = new File ("A").equals (new File ("a"));  //ファイル名の大文字と小文字が区別されるか
   170:     fmtInit ();  //BCD 10進数変換
   171:     Multilingual.mlnInit ();  //MLN 多言語化  sgsInit()よりも前
   172: 
   173:     System.out.println (Multilingual.mlnJapanese ? "java.vendor は " + prgJavaVendor + " です" :
   174:                         "java.vendor is " + prgJavaVendor);
   175:     System.out.println (Multilingual.mlnJapanese ? "java.version は " + prgJavaVersion + " です" :
   176:                         "java.version is " + prgJavaVersion);
   177:     System.out.println (Multilingual.mlnJapanese ? "os.arch は " + prgOsArch + " です" :
   178:                         "os.arch is " + prgOsArch);
   179:     System.out.println (Multilingual.mlnJapanese ? "os.name は " + prgOsName + " です" :
   180:                         "os.name is " + prgOsName);
   181: 
   182:     //WindowsのときDLLを読み込む
   183:     prgWindllLoaded = false;
   184:     if (prgIsWindows) {
   185:       try {
   186:         System.loadLibrary (PRG_WINDLL_NAME);
   187:         if (PRG_WINDLL_VERSION <= WinDLL.version ()) {
   188:           prgWindllLoaded = true;
   189:           System.out.println (Multilingual.mlnJapanese ?
   190:                               PRG_WINDLL_NAME + ".dll を読み込みました" :
   191:                               PRG_WINDLL_NAME + ".dll was read");
   192:         } else {
   193:           System.out.println (Multilingual.mlnJapanese ?
   194:                               PRG_WINDLL_NAME + ".dll のバージョンが違います" :
   195:                               PRG_WINDLL_NAME + ".dll version mismatch");
   196:         }
   197:       } catch (UnsatisfiedLinkError ule) {  //ファイルが見つからない
   198:         System.out.println (Multilingual.mlnJapanese ?
   199:                             PRG_WINDLL_NAME + ".dll を読み込めません" :
   200:                             PRG_WINDLL_NAME + ".dll cannot be read");
   201:       }
   202:     }
   203: 
   204:     rbtInit ();  //RBT ロボット
   205: 
   206:     Settings.sgsInit ();  //SGS 設定  mlnInit()よりも後、他の~Init()よりも前
   207:     LnF.lnfInit ();  //Look&Feel
   208: 
   209:     CharacterCode.chrInit ();  //CHR 文字コード
   210: 
   211:     TickerQueue.tkqInit ();  //TKQ ティッカーキュー
   212: 
   213:     RS232CTerminal.trmInit ();  //TRM RS-232C設定とターミナル。tkqInitよりも後
   214: 
   215:     xt3Init ();  //XT3 Xellent30
   216:     mdlInit ();  //MDL 機種。sgsInit()よりも後
   217: 
   218:     if (InstructionBreakPoint.IBP_ON) {
   219:       InstructionBreakPoint.ibpInit ();  //IBP 命令ブレークポイント
   220:     }
   221:     if (DataBreakPoint.DBP_ON) {
   222:       DataBreakPoint.dbpInit ();  //DBP データブレークポイント
   223:     }
   224:     busInit ();  //BUS バスコントローラ  ibpInit()とdbpInit()よりも後
   225:     MainMemory.mmrInit ();  //MMR メインメモリ。romInitよりも前
   226:     ROM.romInit ();  //ROM ROM。mpuInit()よりも前。mmrInitよりも後
   227:     graInit ();  //GRA グラフィック画面
   228:     txtInit ();  //TXT テキスト画面
   229:     CRTC.crtInit ();  //CRT CRTコントローラ
   230:     VideoController.vcnInit ();  //VCN ビデオコントローラ
   231:     HD63450.dmaInit ();  //DMA DMAコントローラ
   232:     svsInit ();  //SVS スーパーバイザ領域設定
   233:     MC68901.mfpInit ();  //MFP MFP
   234:     RP5C15.rtcInit ();  //RTC RTC
   235:     sysInit ();  //SYS システムポート
   236:     if (OPMLog.OLG_ON) {
   237:       OPMLog.olgInit ();  //OLG OPMログ。opmInitよりも前
   238:     }
   239:     OPM.opmInit ();  //OPM FM音源
   240:     ADPCM.pcmInit ();  //PCM ADPCM音源
   241:     FDC.fdcInit ();  //FDC FDコントローラ
   242:     HDC.hdcInit ();  //HDC SASI HDコントローラ
   243:     SPC.spcInit ();  //SPC SCSIプロトコルコントローラ
   244:     if (SUK.SUK_ON) {
   245:       SUK.sukInit ();  //SUK すかじーU君改
   246:     }
   247:     Z8530.sccInit ();  //SCC SCC  rbtInit()よりも後
   248:     IOInterrupt.ioiInit ();  //IOI I/O割り込み
   249:     SpriteScreen.sprInit ();  //SPR スプライト画面
   250:     bnkInit ();  //BNK バンクメモリ
   251:     SRAM.smrInit ();  //SMR SRAM
   252: 
   253:     PPI.ppiInit ();  //PPI PPI
   254:     PrinterPort.prnInit ();  //PRN プリンタポート
   255:     Indicator.indInit ();  //IND インジケータ
   256: 
   257:     SlowdownTest.sdtInit ();  //SDT 鈍化テスト
   258:     Keyboard.kbdInit ();  //KBD キーボード  keydlyとkeyrepはSRAMが先なのでsmrInit()よりも後
   259:     CONDevice.conInit ();  //CON CONデバイス制御
   260:     Mouse.musInit ();  //MUS マウス
   261:     pnlInit ();  //PNL パネル
   262:     frmInit ();  //FRM フレーム
   263: 
   264:     dbgInit ();  //DBG デバッガ共通コンポーネント
   265:     RegisterList.drpInit ();  //DRP レジスタ
   266:     DisassembleList.ddpInit ();  //DDP 逆アセンブルリスト
   267:     MemoryDumpList.dmpInit ();  //DMP メモリダンプリスト
   268:     LogicalSpaceMonitor.atwInit ();  //ATW アドレス変換ウインドウ
   269:     PhysicalSpaceMonitor.paaInit ();  //PAA 物理アドレス空間ウインドウ
   270:     DebugConsole.dgtInit ();  //DGT デバッグコンソール
   271:     if (BranchLog.BLG_ON) {
   272:       BranchLog.blgInit ();  //BLG 分岐ログ
   273:     }
   274:     if (ProgramFlowVisualizer.PFV_ON) {
   275:       ProgramFlowVisualizer.pfvInit ();  //PFV プログラムフロービジュアライザ
   276:     }
   277:     if (RasterBreakPoint.RBP_ON) {
   278:       RasterBreakPoint.rbpInit ();  //RBP ラスタブレークポイント
   279:     }
   280:     if (ScreenModeTest.SMT_ON) {
   281:       ScreenModeTest.smtInit ();  //SMT 表示モードテスト
   282:     }
   283:     if (RootPointerList.RTL_ON) {
   284:       RootPointerList.rtlInit ();  //RTL ルートポインタリスト
   285:     }
   286:     if (SpritePatternViewer.SPV_ON) {
   287:       SpritePatternViewer.spvInit ();  //SPV スプライトパターンビュア
   288:     }
   289:     if (ATCMonitor.ACM_ON) {
   290:       ATCMonitor.acmInit ();  //ACM アドレス変換キャッシュモニタ
   291:     }
   292: 
   293:     SoundSource.sndInit ();  //SND サウンド
   294:     FEFunction.fpkInit ();  //FPK FEファンクション
   295:     mpuInit ();  //MPU MPU。romInit()よりも後
   296:     MC68060.mmuInit ();  //MMU メモリ管理ユニット
   297:     SoundMonitor.smnInit ();  //SMN 音声モニタ
   298:     HFS.hfsInit ();  //HFS ホストファイルシステムインタフェイス
   299: 
   300:     GIFAnimation.gifInit ();  //GIF GIFアニメーション
   301: 
   302:     //コンポーネントを作る
   303:     //  他のコンポーネントを参照するときは順序に注意する
   304:     Settings.sgsMakeMenu ();  //SGS 設定  mnbMakeMenu()よりも前
   305:     mdlMakeMenu ();  //MDL 機種  mnbMakeMenu(),mpuMakeMenu()よりも前
   306:     FDC.fdcMakeMenu ();  //FDC FDコントローラ  mnbMakeMenu()よりも前
   307:     HDC.hdcMakeMenu ();  //HDC SASI HDコントローラ  mdlMakeMenu()よりも後,mnbMakeMenu()よりも前
   308:     SPC.spcMakeMenu ();  //SPC SCSIプロトコルコントローラ  mdlMakeMenu()よりも後,mnbMakeMenu()よりも前
   309:     mpuMakeMenu ();  //MPU MPU  mdlMakeMenu()よりも後,mnbMakeMenu()よりも前
   310:     SRAM.smrMakeMenu ();  //SMR SRAM  mnbMakeMenu()よりも前
   311:     mnbMakeMenu ();  //MNB メニューバー
   312:     pnlMake ();  //PNL パネル
   313:     frmMake ();  //FRM フレーム
   314:     clpMake ();  //CLP クリップボード
   315:     dbgMakePopup ();  //DBG デバッガ共通コンポーネント
   316: 
   317:     //デバッグフラグを消し忘れないようにする
   318:     final String flags = (
   319:       "" +
   320:       (EFPBox.CIR_DEBUG_TRACE ? " EFPBox.CIR_DEBUG_TRACE" : "") +
   321:       (FDC.FDC_DEBUG_TRACE ? " FDC.FDC_DEBUG_TRACE" : "") +
   322:       (FEFunction.FPK_DEBUG_TRACE ? " FEFunction.FPK_DEBUG_TRACE" : "") +
   323:       (HD63450.DMA_DEBUG_TRACE != 0 ? " HD63450.DMA_DEBUG_TRACE" : "") +
   324:       (HDC.HDC_DEBUG_TRACE ? " HDC.HDC_DEBUG_TRACE" : "") +
   325:       (HDC.HDC_DEBUG_COMMAND ? " HDC.HDC_DEBUG_COMMAND" : "") +
   326:       (HFS.HFS_DEBUG_TRACE ? " HFS.HFS_DEBUG_TRACE" : "") +
   327:       (HFS.HFS_DEBUG_FILE_INFO ? " HFS.HFS_DEBUG_FILE_INFO" : "") +
   328:       (HFS.HFS_COMMAND_TRACE ? " HFS.HFS_COMMAND_TRACE" : "") +
   329:       (HFS.HFS_BUFFER_TRACE ? " HFS.HFS_BUFFER_TRACE" : "") +
   330:       (IOInterrupt.IOI_DEBUG_TRACE ? " IOInterrupt.IOI_DEBUG_TRACE" : "") +
   331:       (Keyboard.KBD_DEBUG_LED ? " Keyboard.KBD_DEBUG_LED" : "") +
   332:       (M68kException.M6E_DEBUG_ERROR ? " M68kException.M6E_DEBUG_ERROR" : "") +
   333:       (MC68060.MMU_DEBUG_COMMAND ? " MC68060.MMU_DEBUG_COMMAND" : "") +
   334:       (MC68060.MMU_DEBUG_TRANSLATION ? " MC68060.MMU_DEBUG_TRANSLATION" : "") +
   335:       (MC68060.MMU_NOT_ALLOCATE_CACHE ? " MC68060.MMU_NOT_ALLOCATE_CACHE" : "") +
   336:       (RP5C15.RTC_DEBUG_TRACE ? " RP5C15.RTC_DEBUG_TRACE" : "") +
   337:       (SPC.SPC_DEBUG_ON ? " SPC.SPC_DEBUG_ON" : "") +
   338:       (Z8530.SCC_DEBUG_ON ? " Z8530.SCC_DEBUG_ON" : "")
   339:       );
   340:     if (!"".equals (flags)) {
   341:       pnlExitFullScreen (true);
   342:       JOptionPane.showMessageDialog (null, "debug flags:" + flags);
   343:     }
   344: 
   345:     //動作を開始する
   346:     //  イベントリスナーを設定する
   347:     //  タイマーを起動する
   348:     tmrStart ();  //TMR タイマー
   349: 
   350:     Keyboard.kbdStart ();  //KBD キーボード
   351:     Mouse.musStart ();  //MUS マウス
   352:     pnlStart ();  //PNL パネル
   353:     frmStart ();  //FRM フレーム
   354:     SoundSource.sndStart ();  //SND サウンド
   355: 
   356:     if (DataBreakPoint.DBP_ON) {
   357:       DataBreakPoint.dbpStart ();  //DBP データブレークポイント
   358:     }
   359:     if (RasterBreakPoint.RBP_ON) {
   360:       RasterBreakPoint.rbpStart ();  //RBP ラスタブレークポイント
   361:     }
   362:     if (ScreenModeTest.SMT_ON) {
   363:       ScreenModeTest.smtStart ();  //SMT 表示モードテスト
   364:     }
   365:     if (OPMLog.OLG_ON) {
   366:       OPMLog.olgStart ();  //OLG OPMログ
   367:     }
   368:     SoundMonitor.smnStart ();  //SMN 音声モニタ
   369:     RS232CTerminal.trmStart ();  //TRM ターミナルウインドウ
   370:     PPI.ppiStart ();  //PPI PPI
   371:     PrinterPort.prnStart ();  //PRN プリンタポート
   372:     if (BranchLog.BLG_ON) {
   373:       BranchLog.blgStart ();  //BLG 分岐ログ
   374:     }
   375:     if (ProgramFlowVisualizer.PFV_ON) {
   376:       ProgramFlowVisualizer.pfvStart ();  //PFV プログラムフロービジュアライザ
   377:     }
   378:     RegisterList.drpStart ();  //DRP レジスタ
   379:     DisassembleList.ddpStart ();  //DDP 逆アセンブルリスト
   380:     MemoryDumpList.dmpStart ();  //DMP メモリダンプリスト
   381:     LogicalSpaceMonitor.atwStart ();  //ATW アドレス変換ウインドウ
   382:     PhysicalSpaceMonitor.paaStart ();  //PAA 物理アドレス空間ウインドウ
   383:     DebugConsole.dgtStart ();  //DGT コンソール
   384:     if (RootPointerList.RTL_ON) {
   385:       RootPointerList.rtlStart ();  //RTL ルートポインタリスト
   386:     }
   387:     if (SpritePatternViewer.SPV_ON) {
   388:       SpritePatternViewer.spvStart ();  //SPV スプライトパターンビュア
   389:     }
   390:     if (ATCMonitor.ACM_ON) {
   391:       ATCMonitor.acmStart ();  //ACM アドレス変換キャッシュモニタ
   392:     }
   393: 
   394:     if (Settings.sgsSaveiconValue != null) {
   395:       String[] a = Settings.sgsSaveiconValue.split (",");
   396:       if (0 < a.length) {
   397:         saveIcon (a[0], LnF.LNF_ICON_IMAGES);
   398:         if (1 < a.length) {
   399:           saveImage (LnF.LNF_ICON_IMAGE_16, a[1]);
   400:           if (2 < a.length) {
   401:             saveImage (LnF.LNF_ICON_IMAGE_32, a[2]);
   402:             if (3 < a.length) {
   403:               saveImage (LnF.LNF_ICON_IMAGE_48, a[3]);
   404:             }
   405:           }
   406:         }
   407:       }
   408:       prgTini ();
   409:       return;
   410:     }
   411: 
   412:     //コアを起動する
   413:     mpuReset (-1, -1);
   414: 
   415:     //全画面表示に切り替える
   416:     if (pnlIsFullscreenSupported && pnlFullscreenRequest) {
   417:       pnlFullscreenTimer = new javax.swing.Timer (PNL_FULLSCREEN_DELAY, new ActionListener () {
   418:         public void actionPerformed (ActionEvent ae) {
   419:           mnbFullscreenMenuItem.doClick ();
   420:           pnlFullscreenTimer.stop ();
   421:           pnlFullscreenTimer = null;
   422:         }
   423:       });
   424:       pnlFullscreenTimer.start ();
   425:     }
   426: 
   427:   }  //コンストラクタ
   428: 
   429: 
   430: 
   431:   //prgTini ()
   432:   //  プログラムの後始末
   433:   public static void prgTini () {
   434:     try {
   435:       if (OPMLog.OLG_ON) {
   436:         OPMLog.olgTini ();  //OLG OPMログ
   437:       }
   438:       GIFAnimation.gifTini ();  //GIFアニメーション
   439:       SoundSource.sndTini ();  //SND サウンド
   440:       Keyboard.kbdTini ();  //KBD キーボード
   441:       Mouse.musTini ();  //MUS マウス
   442:       CONDevice.conTini ();  //CON CONデバイス制御
   443:       PPI.ppiTini ();  //PPI PPI
   444:       PrinterPort.prnTini ();  //PRN プリンタポート
   445:       FDC.fdcTini ();  //FDC FDコントローラ
   446:       HDC.hdcTini ();  //HDC SASI HDコントローラ
   447:       SPC.spcTini ();  //SPC SCSIプロトコルコントローラ
   448:       if (SUK.SUK_ON) {
   449:         SUK.sukTini ();  //SUK すかじーU君改
   450:       }
   451:       HFS.hfsTini ();  //HFS ホストファイルシステムインタフェイス
   452:       Z8530.sccTini ();  //SCC SCC
   453:       CRTC.crtTini ();  //CRT CRTコントローラ
   454:       SpriteScreen.sprTini ();  //SPR スプライト画面
   455:       pnlTini ();  //PNL パネル
   456:       bnkTini ();  //BNK バンクメモリ
   457:       ROM.romTini ();  //ROM
   458:       xt3Tini ();  //XT3 Xellent30
   459:       mdlTini ();  //MDL 機種
   460:       SRAM.smrTini ();  //SMR SRAM
   461:       tmrTini ();  //TMR タイマー
   462:       busTini ();  //BUS バスコントローラ
   463:       RS232CTerminal.trmTini ();  //TRM RS-232C設定とターミナル
   464:       LnF.lnfTini ();
   465:       Settings.sgsTini ();  //SGS 設定
   466:     } catch (Exception e) {  //終了時に予期しないエラーが発生すると終了できなくなってしまうので、すべてのExceptionをcatchする
   467:       e.printStackTrace ();
   468:     }
   469:     System.exit (0);
   470:   }  //prgTini()
   471: 
   472:   //prgOpenJavaDialog ()
   473:   //  Java実行環境の情報
   474:   public static void prgOpenJavaDialog () {
   475:     pnlExitFullScreen (true);
   476:     JOptionPane.showMessageDialog (
   477:       frmFrame,
   478:       ComponentFactory.createGridPanel (
   479:         3,  //colCount
   480:         6,  //rowCount
   481:         "paddingLeft=6,paddingRight=6",  //gridStyles
   482:         "italic,right;left;left",  //colStyless
   483:         "italic,center;colSpan=3,widen",  //rowStyless
   484:         "",  //cellStyless
   485:         //
   486:         null,  //(0,0)
   487:         Multilingual.mlnJapanese ? "実行中" : "Running",  //(1,0)
   488:         Multilingual.mlnJapanese ? "推奨" : "Recommended",  //(2,0)
   489:         //
   490:         ComponentFactory.createHorizontalSeparator (),  //(0,1)
   491:         //
   492:         Multilingual.mlnJapanese ? "Java のベンダー" : "Java Vendor",  //(0,2)
   493:         prgJavaVendor,  //(1,2)
   494:         PRG_JAVA_VENDOR,  //(2,2)
   495:         //
   496:         Multilingual.mlnJapanese ? "Java のバージョン" : "Java Version",  //(0,3)
   497:         prgJavaVersion,  //(1,3)
   498:         PRG_JAVA_VERSION,  //(2,3)
   499:         //
   500:         Multilingual.mlnJapanese ? "OS のアーキテクチャ" : "OS Architecture",  //(0,4)
   501:         prgOsArch,  //(1,4)
   502:         PRG_OS_ARCH,  //(2,4)
   503:         //
   504:         Multilingual.mlnJapanese ? "OS の名前" : "OS Name",  //(0,5)
   505:         prgOsName,  //(1,5)
   506:         PRG_OS_NAME  //(2,5)
   507:         ),
   508:       Multilingual.mlnJapanese ? "Java 実行環境の情報" : "Java runtime environment information",
   509:       JOptionPane.PLAIN_MESSAGE);
   510:   }  //prgOpenJavaDialog()
   511: 
   512:   //prgOpenAboutDialog ()
   513:   //  バージョン情報
   514:   public static void prgOpenAboutDialog () {
   515:     pnlExitFullScreen (true);
   516:     JOptionPane.showMessageDialog (
   517:       frmFrame,
   518:       ComponentFactory.createGridPanel (
   519:         2, 4, "paddingLeft=6,paddingRight=6", "italic,right;left", "", "",
   520:         Multilingual.mlnJapanese ? "タイトル" : "Title"  ,  //(0,0)
   521:         PRG_TITLE,  //(1,0)
   522:         Multilingual.mlnJapanese ? "バージョン" : "Version",  //(0,1)
   523:         PRG_VERSION,  //(1,1)
   524:         Multilingual.mlnJapanese ? "作者" : "Author" ,  //(0,2)
   525:         PRG_AUTHOR,  //(1,2)
   526:         Multilingual.mlnJapanese ? "ウェブページ" : "Webpage",  //(0,3)
   527:         PRG_WEBPAGE  //(1,3)
   528:         ),
   529:       Multilingual.mlnJapanese ? "バージョン情報" : "Version information",
   530:       JOptionPane.PLAIN_MESSAGE);
   531:   }  //prgOpenAboutDialog()
   532: 
   533:   //prgOpenXEiJLicenseDialog ()
   534:   //  XEiJライセンスダイアログ
   535:   public static void prgOpenXEiJLicenseDialog () {
   536:     pnlExitFullScreen (true);
   537:     JOptionPane.showMessageDialog (
   538:       frmFrame,
   539:       ComponentFactory.createScrollTextPane (rscGetResourceText ("license_XEiJ.txt"), 550, 300),
   540:       Multilingual.mlnJapanese ? "XEiJ 使用許諾条件" : "XEiJ License",
   541:       JOptionPane.PLAIN_MESSAGE);
   542:   }  //prgOpenXEiJLicenseDialog()
   543: 
   544:   //prgOpenSHARPLicenseDialog ()
   545:   //  FSHARPライセンスダイアログ
   546:   public static void prgOpenSHARPLicenseDialog () {
   547:     pnlExitFullScreen (true);
   548:     JOptionPane.showMessageDialog (
   549:       frmFrame,
   550:       ComponentFactory.createScrollTextPane (rscGetResourceText ("license_FSHARP.txt", "Shift_JIS"), 550, 300),
   551:       Multilingual.mlnJapanese ? "無償公開された X68000 の基本ソフトウェア製品の許諾条件" : "License of the basic software products for X68000 that were distributed free of charge",
   552:       JOptionPane.PLAIN_MESSAGE);
   553:   }  //prgOpenSHARPLicenseDialog()
   554: 
   555:   //prgOpenYmfmLicenseDialog ()
   556:   //  ymfmライセンスダイアログ
   557:   public static void prgOpenYmfmLicenseDialog () {
   558:     pnlExitFullScreen (true);
   559:     JOptionPane.showMessageDialog (
   560:       frmFrame,
   561:       ComponentFactory.createScrollTextPane (rscGetResourceText ("license_ymfm.txt"), 550, 300),
   562:       "ymfm License",
   563:       JOptionPane.PLAIN_MESSAGE);
   564:   }  //prgOpenYmfmLicenseDialog()
   565: 
   566:   //prgOpenJSerialCommLicenseDialog ()
   567:   //  jSerialCommライセンスダイアログ
   568:   public static void prgOpenJSerialCommLicenseDialog () {
   569:     pnlExitFullScreen (true);
   570:     JOptionPane.showMessageDialog (
   571:       frmFrame,
   572:       ComponentFactory.createVerticalSplitPane (
   573:         ComponentFactory.createScrollTextPane (rscGetResourceText ("LICENSE-APACHE-2.0"), 550, 300),
   574:         ComponentFactory.createScrollTextPane (rscGetResourceText ("LICENSE-LGPL-3.0"), 550, 300)
   575:         ),
   576:       "jSerialComm License",
   577:       JOptionPane.PLAIN_MESSAGE);
   578:   }  //prgOpenJSerialCommLicenseDialog()
   579: 
   580:   //prgPrintClass (o)
   581:   //  オブジェクトを表示する
   582:   public static void prgPrintClass (Object o) {
   583:     System.out.println (o.toString ());
   584:     //スーパークラスを遡る
   585:     try {
   586:       Stack<Class<?>> s = new Stack<Class<?>> ();
   587:       for (Class<?> c = o.getClass (); c != null; c = c.getSuperclass ()) {
   588:         s.push (c);
   589:       }
   590:       for (int i = 0; !s.empty (); i++) {
   591:         for (int j = 0; j < i; j++) {
   592:           System.out.print ("  ");
   593:         }
   594:         System.out.println (s.pop ().getName ());
   595:       }
   596:     } catch (Exception e) {
   597:     }
   598:   }  //prgPrintClass(Object)
   599: 
   600:   //prgPrintStackTrace ()
   601:   //  スタックトレースを表示する
   602:   //  メソッドがどのような経路で呼び出されたか確認したいときに使う
   603:   public static void prgPrintStackTrace () {
   604:     Exception e = new Exception ();
   605:     e.fillInStackTrace ();
   606:     prgPrintStackTraceOf (e);
   607:   }  //prgPrintStackTrace()
   608:   public static void prgPrintStackTraceOf (Exception e) {
   609:     //e.printStackTrace ();
   610:     System.out.println ("------------------------------------------------");
   611:     System.out.println (e.toString ());
   612:     System.out.println ("\t" + e.getMessage ());
   613:     for (StackTraceElement ste : e.getStackTrace ()) {
   614:       System.out.println ("\tat " + ste.toString ());
   615:     }
   616:     System.out.println ("------------------------------------------------");
   617:   }  //prgPrintStackTraceOf()
   618: 
   619:   //prgStopOnce ()
   620:   //  1回目だけ停止する。2回目以降は何もしない
   621:   //  特定の条件で止めて近くにブレークポイントを仕掛けたいときに使う
   622:   public static boolean prgStopDone = false;
   623:   public static void prgStopOnce () {
   624:     if (!prgStopDone) {
   625:       prgStopDone = true;
   626:       mpuStop (null);
   627:     }
   628:   }  //prgStopOnce()
   629: 
   630: 
   631: 
   632:   //========================================================================================
   633:   //$$TMR タイマ
   634:   //  tmrTimerは1つだけ存在する
   635:   //  1つのタイマにスケジュールされたタスクはオーバーラップしない
   636:   //  固定遅延実行
   637:   //    tmrTimer.schedule (task, delay, interval)
   638:   //    次回の実行開始予定時刻=max(今回の実行終了時刻,今回の実行開始時刻+interval)
   639:   //  固定頻度実行
   640:   //    tmrTimer.scheduleAtFixedRate (task, delay, interval)
   641:   //    次回の実行開始予定時刻=max(今回の実行終了時刻,初回の実行開始時刻+interval*今回までの実行回数)
   642: 
   643:   //時刻の周波数
   644:   //  mpuClockTimeなどのカウンタが1秒間に進む数
   645:   //  10^10のとき
   646:   //    1周期   0.1nanosecond
   647:   //    2^31-1  0.2second
   648:   //    2^53-1  10day
   649:   //    2^63-1  29year
   650:   //  10^11のとき
   651:   //    1周期   10picosecond
   652:   //    2^31-1  21millisecond
   653:   //    2^53-1  1day
   654:   //    2^63-1  2.9year
   655:   //  10^12のとき
   656:   //    1周期   1picosecond
   657:   //    2^31-1  2.1millisecond
   658:   //    2^53-1  2.5hour
   659:   //    2^63-1  3.5month
   660:   public static final long TMR_FREQ = 1000000000000L;  //10^12Hz。1ps
   661: 
   662:   //メインタイマ
   663:   public static final long TMR_DELAY = 10L;  //ms
   664:   public static final long TMR_INTERVAL = 10L;  //ms
   665: 
   666:   //タイマ
   667:   public static java.util.Timer tmrTimer;  //Timerだけだとjavax.swing.Timerと紛らわしい
   668: 
   669:   //tmrStart ()
   670:   //  タイマを開始する
   671:   public static void tmrStart () {
   672:     tmrTimer = new java.util.Timer ();  //Timerだけだとjavax.swing.Timerと紛らわしい
   673:   }  //tmrStart()
   674: 
   675:   //tmrTini ()
   676:   //  タイマの後始末
   677:   public static void tmrTini () {
   678:     if (tmrTimer != null) {
   679:       tmrTimer.cancel ();
   680:     }
   681:   }  //tmrTini()
   682: 
   683: 
   684: 
   685:   //========================================================================================
   686:   //$$PNL パネル
   687:   //
   688:   //  固定倍率のとき
   689:   //    パネルの最小サイズはスクリーンのサイズに固定倍率を掛けて切り上げた値
   690:   //    スクリーンの表示サイズはスクリーンのサイズに固定倍率を掛けて丸めた値
   691:   //  ウインドウに合わせるとき
   692:   //    倍率は
   693:   //      パネルの幅をスクリーンの幅で割った結果
   694:   //      パネルの高さからキーボードの高さを引いてスクリーンの高さで割った結果
   695:   //    のどちらか小さい方
   696:   //
   697:   //  スクリーンの大きさに固定倍率を掛けて丸めた値から倍率を逆算すると固定倍率よりも小さくなってしまう場合がある
   698:   //
   699:   //  全画面表示
   700:   //    キーボードと合わせてパネルにちょうど入り切るようにスクリーンの拡大率と表示位置を計算する
   701:   //  ウインドウに合わせる
   702:   //    可能ならばユーザがパネルの大きさを変更できるようにする
   703:   //    パネルの大きさが最小倍率で入り切らないとき
   704:   //      プログラムがパネルの大きさを変更できるとき
   705:   //        パネルの大きさを最小倍率でちょうど入り切る大きさに変更する
   706:   //      パネルの中央に表示する
   707:   //    パネルの大きさが最小倍率で入り切るとき
   708:   //      パネルの大きさに合わせてスクリーンを拡大縮小する
   709:   //  固定倍率
   710:   //    可能ならばユーザがパネルの大きさを変更できないようにする
   711:   //    プログラムがパネルの大きさを変更できるとき
   712:   //      パネルの大きさを固定倍率でちょうど入り切る大きさに変更する
   713:   //    スクリーンを拡大縮小してキーボードと一緒にパネルの中央に表示する
   714: 
   715: 
   716:   //ビットマップのサイズ
   717:   public static final int PNL_BM_OFFSET_BITS = 10;
   718:   public static final int PNL_BM_WIDTH = 1 << PNL_BM_OFFSET_BITS;
   719:   public static final int PNL_BM_HEIGHT = 1024;
   720: 
   721:   //アスペクト比
   722:   public static final int PNL_ASPECT_KEYS = 4;
   723:   public static final int PNL_ASPECT_VALUES = 4;
   724:   public static final int[] PNL_ASPECT_DEFAULT_VALUE = { 0, 0, 0, 3 };  //[key]=defaultValue
   725:   public static final String[] PNL_ASPECT_RESOLUTION_NAME = { "256x256", "384x256", "512x512", "768x512" };  //[key]=resolutionName
   726:   public static final String[] PNL_ASPECT_SCREEN_NAME = { "4:3", "7:5", "13:9", "3:2" };  //[value]=screenAspectRatioName
   727:   public static final String[] PNL_ASPECT_PIXEL_NAME = { "8:9", "14:15", "26:27", "1:1" };  //[value]=pixelAspectRatioName
   728:   public static final float[] PNL_ASPECT_SCREEN_RATIO = { 4.0F / 3.0F, 7.0F / 5.0F, 13.0F / 9.0F, 3.0F / 2.0F };  //[value]=screenAspectRatio,pixelAspectRatio(256x256/512x512)
   729:   public static final float[] PNL_ASPECT_PIXEL_RATIO = { 8.0F / 9.0F, 14.0F / 15.0F, 26.0F / 27.0F, 1.0F / 1.0F };  //[value]=pixelAspectRatio(384x256/768x512)
   730:   public static final float[][] PNL_ASPECT_MATRIX = {
   731:     PNL_ASPECT_SCREEN_RATIO,
   732:     PNL_ASPECT_PIXEL_RATIO,
   733:     PNL_ASPECT_SCREEN_RATIO,
   734:     PNL_ASPECT_PIXEL_RATIO,
   735:   };  //[key][value]=pixelAspectRatio
   736:   public static int[] pnlAspectMap;  //[key]=value
   737:   public static float[] pnlAspectTable;  //[CRTC.crtHRLCurr<<2|CRTC.crtHResoCurr]=pixelAspectRatio
   738: 
   739:   //サイズと位置
   740:   public static int pnlScreenWidth;  //X68000から見た表示領域のサイズ。幅は常に8の倍数
   741:   public static int pnlScreenHeight;
   742:   public static float pnlStretchMode;  //水平方向の拡大率。pnlAspectTable[CRTC.crtHRLCurr<<2|CRTC.crtHResoCurr]
   743:   public static int pnlStretchWidth;  //ピクセルの縦横比に合わせて伸縮された表示領域の幅。Math.round((float)pnlScreenWidth*pnlStretchMode)
   744:   public static int pnlZoomWidth;  //描画サイズ。pnlStretchWidth,pnlScreenHeightを同じ比率で拡大
   745:   public static int pnlZoomHeight;
   746:   public static int pnlZoomRatioOut;  //65536*pnlZoomHeight/pnlScreenHeight
   747:   public static int pnlZoomRatioInX;  //65536*pnlScreenWidth/pnlZoomWidth
   748:   public static int pnlZoomRatioInY;  //65536*pnlScreenHeight/pnlZoomHeight
   749:   public static int pnlWidth;  //パネルのサイズ
   750:   public static int pnlHeight;
   751:   public static Dimension pnlSize;  //パネルの推奨サイズ。pnlWidth,pnlHeight
   752:   public static int pnlScreenX1;  //スクリーンのX座標。1=左開始,2=左終了,3=右開始,4=右終了
   753:   public static int pnlScreenX2;
   754:   public static int pnlScreenX3;
   755:   public static int pnlScreenX4;
   756:   public static int pnlScreenY1;  //スクリーンのY座標。1=上開始,2=上終了,3=下開始,4=下終了
   757:   public static int pnlScreenY2;
   758:   public static int pnlScreenY3;
   759:   public static int pnlScreenY4;
   760:   public static int pnlKeyboardX;  //キーボードの表示位置。pnlUpdateArrangement()が設定する
   761:   public static int pnlKeyboardY;
   762:   public static int pnlMinimumWidth;  //パネルの最小サイズ
   763:   public static int pnlMinimumHeight;
   764:   public static int pnlGlobalX;  //画面上の表示位置
   765:   public static int pnlGlobalY;
   766: 
   767:   //モード
   768:   public static final boolean PNL_FILL_BACKGROUND = true;  //true=常に背景を塗り潰してから描画する
   769:   public static boolean pnlFillBackgroundRequest;  //true=次回のpaintで背景を塗り潰す
   770:   public static boolean pnlIsFullscreenSupported;  //true=全画面表示に移行できる
   771:   public static boolean pnlFullscreenOn;  //true=全画面表示
   772:   public static boolean pnlIsFitInWindowSupported;  //true=ウインドウに合わせられる
   773:   public static boolean pnlFitInWindowOn;  //true=ウインドウに合わせる
   774:   public static boolean pnlPrevFitInWindowOn;  //true=全画面表示にする前はウインドウに合わせていた
   775:   public static boolean pnlPrevKeyboardOn;  //true=全画面表示に移行する前はキーボードを表示していた
   776: 
   777:   //全画面表示に切り替える
   778:   public static final int PNL_FULLSCREEN_DELAY = 500;  //全画面表示に切り替えるタイマーのディレイタイム(ms)
   779:   public static boolean pnlFullscreenRequest;  //true=全画面表示に切り替える
   780:   public static javax.swing.Timer pnlFullscreenTimer;  //全画面表示に切り替えるタイマー
   781: 
   782:   //補間アルゴリズム
   783:   //  RenderingHints.VALUE_INTERPOLATION_NEAREST_NEIGHBOR  軽い
   784:   //  RenderingHints.VALUE_INTERPOLATION_BILINEAR          頑張る
   785:   //  RenderingHints.VALUE_INTERPOLATION_BICUBIC           重すぎる?
   786:   public static Object pnlInterpolation;  //補間アルゴリズム
   787: 
   788:   //イメージとビットマップ
   789:   //
   790:   //  立体視OFFのとき
   791:   //    左に描く
   792:   //    左を表示する
   793:   //
   794:   //  立体視ONのとき
   795:   //    垂直映像開始で
   796:   //      0=3=左右OPENまたは2=左OPENのとき
   797:   //        左に描く
   798:   //      1=右OPENのとき
   799:   //        右に描く
   800:   //    drawRasterの後で
   801:   //      0=3=左右OPENのとき
   802:   //        左から右へコピー
   803:   //    左右を表示する
   804:   //
   805:   //  シャッターの左右CLOSEは左右OPENとみなす
   806:   //    TVコントロール信号の送信で$00E8E003に$08や$00が書き込まれて左右CLOSEされてしまう
   807:   //    左右CLOSEすると何も表示されないので止まってしまったように見える
   808:   //    接続ケーブル配線図によると~3DRだけで左OPENと右OPENを切り替えており左右CLOSEは存在しない
   809:   //
   810:   //  X68000-ファミコン3Dシステム接続ケーブル配線図
   811:   //            X68000 STEREOSCOPIC端子側
   812:   //            6pin Mini-DIN オス 半田面
   813:   //                ┌─┐    ┌─┐
   814:   //              ┌┘  └──┘  └┐
   815:   //            ┌┘   GND    GND   └┐
   816:   //            │      ○6  5○────┐
   817:   //            │  VCC1              ││
   818:   //          ┌───○4      3○~3DL││
   819:   //          ││                    ││
   820:   //          ││  ~3DR○2  1○      ││
   821:   //          │└┐    │ VSYNC(3D)┌┘│
   822:   //          │  └┐  │        ┌┘  │
   823:   //          │    └─│────┘    │
   824:   //          │        └──┐        │
   825:   //    ┌──│───────│────│─┐
   826:   //    │  ○│○  ○  ○  ○│○  ○  ○  │
   827:   //    │   8│ 7   6   5   4│ 3   2   1  │
   828:   //    └┐  │              │          ┌┘
   829:   //      │  ○  ○  ○  ○  ○  ○  ○  │
   830:   //      │  15  14  13  12  11  10   9  │
   831:   //      └───────────────┘
   832:   //           D-Sub 15pin オス 半田面
   833:   //           ファミコン3Dシステム側
   834:   //      出典:電脳倶楽部17号(1989年10月号)
   835:   //
   836:   public static final boolean PNL_STEREOSCOPIC_ON = true;
   837:   public static BufferedImage pnlScreenImageLeft;  //イメージ左
   838:   public static BufferedImage pnlScreenImageRight;  //イメージ右
   839:   public static int[] pnlBMLeft;  //ビットマップ左
   840:   public static int[] pnlBMRight;  //ビットマップ右
   841:   public static int[] pnlBM;  //描画するビットマップ
   842:   public static boolean pnlStereoscopicOn;  //true=立体視
   843:   public static final int PNL_NAKED_EYE_CROSSING = 0;  //裸眼交差法
   844:   public static final int PNL_NAKED_EYE_PARALLEL = 1;  //裸眼平行法
   845:   public static final int PNL_SIDE_BY_SIDE       = 2;  //サイドバイサイド
   846:   public static final int PNL_TOP_AND_BOTTOM     = 3;  //トップアンドボトム
   847:   public static int pnlStereoscopicMethod;  //0=裸眼交差法,1=裸眼平行法,2=サイドバイサイド,3=トップアンドボトム
   848:   public static int pnlStereoscopicFactor;  //pnlStereoscopicOn&&(pnlStereoscopicMethod==PNL_NAKED_EYE_CROSSING||pnlStereoscopicMethod==PNL_NAKED_EYE_PARALLEL)?2:1
   849:   public static int pnlStereoscopicShutter;  //$00E8E003のbit1-0。0=3=左右OPEN,1=右OPEN,2=左OPEN
   850: 
   851:   //パネル
   852:   public static JPanel pnlPanel;  //パネル
   853: 
   854:   //メニュー
   855:   public static int pnlFixedScale;
   856:   public static SpinnerNumberModel pnlFixedModel;
   857:   public static JSpinner pnlFixedSpinner;
   858: 
   859:   //pnlInit ()
   860:   //  パネルのフィールドを初期化する
   861:   public static void pnlInit () {
   862: 
   863:     //設定
   864:     //  画面スケーリングモード
   865:     pnlFullscreenRequest = false;
   866:     switch (Settings.sgsGetString ("scaling").toLowerCase ()) {
   867:     case "fullscreen":  //全画面表示
   868:       pnlFullscreenOn = false;
   869:       pnlFitInWindowOn = false;
   870:       pnlFullscreenRequest = true;
   871:       break;
   872:     case "fitinwindow":  //ウインドウに合わせる
   873:       pnlFullscreenOn = false;
   874:       pnlFitInWindowOn = true;
   875:       break;
   876:     case "fixedscale":  //固定倍率
   877:       pnlFullscreenOn = false;
   878:       pnlFitInWindowOn = false;
   879:       break;
   880:     default:
   881:       pnlFullscreenOn = false;
   882:       pnlFitInWindowOn = true;
   883:     }
   884:     //  固定倍率
   885:     pnlFixedScale = Math.max (10, Math.min (1000, Settings.sgsGetInt ("fixedscale")));
   886: 
   887:     //  アスペクト比
   888:     pnlAspectMap = new int[PNL_ASPECT_KEYS];
   889:     for (int key = 0; key < PNL_ASPECT_KEYS; key++) {
   890:       String resolutionName = PNL_ASPECT_RESOLUTION_NAME[key];
   891:       String screenName = Settings.sgsGetString ("aspectratio" + resolutionName);
   892:       int value = PNL_ASPECT_DEFAULT_VALUE[key];
   893:       for (int tempValue = 0; tempValue < PNL_ASPECT_VALUES; tempValue++) {
   894:         if (PNL_ASPECT_SCREEN_NAME[tempValue].equals (screenName)) {
   895:           value = tempValue;
   896:           break;
   897:         }
   898:       }
   899:       pnlAspectMap[key] = value;
   900:     }
   901:     pnlAspectTable = new float[8];
   902:     pnlUpdateAspectTable ();
   903: 
   904:     //  補間アルゴリズム
   905:     switch (Settings.sgsGetString ("interpolation").toLowerCase ()) {
   906:     case "nearest":  //最近傍補間
   907:       pnlInterpolation = RenderingHints.VALUE_INTERPOLATION_NEAREST_NEIGHBOR;
   908:       break;
   909:     case "bilinear":  //線形補間
   910:       pnlInterpolation = RenderingHints.VALUE_INTERPOLATION_BILINEAR;
   911:       break;
   912:     case "bicubic":  //三次補間
   913:       pnlInterpolation = RenderingHints.VALUE_INTERPOLATION_BICUBIC;
   914:       break;
   915:     default:
   916:       pnlInterpolation = RenderingHints.VALUE_INTERPOLATION_BILINEAR;
   917:     }
   918: 
   919:     pnlPrevFitInWindowOn = pnlFitInWindowOn;
   920:     pnlPrevKeyboardOn = true;
   921: 
   922:     //イメージとビットマップ
   923:     pnlScreenImageLeft = new BufferedImage (PNL_BM_WIDTH, PNL_BM_HEIGHT, BufferedImage.TYPE_INT_RGB);
   924:     pnlScreenImageRight = new BufferedImage (PNL_BM_WIDTH, PNL_BM_HEIGHT, BufferedImage.TYPE_INT_RGB);
   925:     pnlBMLeft = ((DataBufferInt) pnlScreenImageLeft.getRaster ().getDataBuffer ()).getData ();
   926:     pnlBMRight = ((DataBufferInt) pnlScreenImageRight.getRaster ().getDataBuffer ()).getData ();
   927:     pnlBM = pnlBMLeft;  //左に描く
   928:     pnlStereoscopicOn = Settings.sgsGetOnOff ("stereoscopic");
   929:     switch (Settings.sgsGetString ("stereoscopicmethod").toLowerCase ()) {
   930:     case "nakedeyecrossing":
   931:       pnlStereoscopicMethod = PNL_NAKED_EYE_CROSSING;
   932:       break;
   933:     case "nakedeyeparallel":
   934:       pnlStereoscopicMethod = PNL_NAKED_EYE_PARALLEL;
   935:       break;
   936:     case "sidebyside":
   937:       pnlStereoscopicMethod = PNL_SIDE_BY_SIDE;
   938:       break;
   939:     case "topandbottom":
   940:       pnlStereoscopicMethod = PNL_TOP_AND_BOTTOM;
   941:       break;
   942:     default:
   943:       pnlStereoscopicMethod = PNL_NAKED_EYE_CROSSING;
   944:     }
   945:     pnlStereoscopicFactor = pnlStereoscopicOn && (pnlStereoscopicMethod == PNL_NAKED_EYE_CROSSING ||
   946:                                                   pnlStereoscopicMethod == PNL_NAKED_EYE_PARALLEL) ? 2 : 1;
   947:     pnlStereoscopicShutter = 0;  //左右OPEN
   948: 
   949:     //サイズと位置
   950:     pnlScreenWidth = 768;
   951:     pnlScreenHeight = 512;
   952:     pnlStretchMode = 1.0F;
   953:     pnlStretchWidth = Math.round ((float) pnlScreenWidth * pnlStretchMode);
   954:     pnlZoomWidth = pnlStretchWidth;
   955:     pnlZoomHeight = pnlScreenHeight;
   956:     pnlWidth = Math.max (pnlZoomWidth * pnlStereoscopicFactor, Keyboard.kbdWidth);
   957:     pnlHeight = pnlZoomHeight + Keyboard.kbdHeight;
   958:     pnlSize = new Dimension (pnlWidth, pnlHeight);
   959:     pnlScreenX1 = (pnlWidth - pnlZoomWidth * pnlStereoscopicFactor) >> 1;
   960:     pnlScreenY1 = 0;
   961:     pnlArrangementCommon ();
   962:     pnlMinimumWidth = Math.max (256, Keyboard.kbdWidth);
   963:     pnlMinimumHeight = 64 + Keyboard.kbdHeight;
   964:     pnlGlobalX = 0;
   965:     pnlGlobalY = 0;
   966: 
   967:     //モード
   968:     if (!PNL_FILL_BACKGROUND) {
   969:       pnlFillBackgroundRequest = true;
   970:     }
   971: 
   972:     //メニュー
   973:     pnlFixedModel = new SpinnerNumberModel (pnlFixedScale, 10, 1000, 1);
   974:     pnlFixedSpinner = ComponentFactory.createNumberSpinner (pnlFixedModel, 4, new ChangeListener () {
   975:       @Override public void stateChanged (ChangeEvent ce) {
   976:         mnbFixedScaleMenuItem.setSelected (true);
   977:         pnlSetFitInWindowOn (false);
   978:         pnlSetFullscreenOn (false);
   979:         pnlUpdateArrangement ();
   980:       }
   981:     });
   982: 
   983:   }  //pnlInit()
   984: 
   985:   //  立体視をon/offする
   986:   public static void pnlSetStereoscopic (boolean on, int method) {
   987:     if (pnlStereoscopicOn != on || pnlStereoscopicMethod != method) {
   988:       pnlStereoscopicMethod = method;
   989:       pnlStereoscopicFactor = on && (pnlStereoscopicMethod == PNL_NAKED_EYE_CROSSING ||
   990:                                      pnlStereoscopicMethod == PNL_NAKED_EYE_PARALLEL) ? 2 : 1;
   991:       if (!pnlStereoscopicOn && on) {  //off→on
   992:         System.arraycopy (pnlBMLeft, 0, pnlBMRight, 0, 1024 * 1024);  //左から右へコピー
   993:       } else if (pnlStereoscopicOn && !on) {  //on→off
   994:         pnlBM = pnlBMLeft;  //左に描く
   995:       }
   996:       pnlStereoscopicOn = on;
   997:       if (pnlFullscreenOn &&  //全画面表示かつ
   998:           pnlStereoscopicOn && (pnlStereoscopicMethod == PNL_SIDE_BY_SIDE ||
   999:                                pnlStereoscopicMethod == PNL_TOP_AND_BOTTOM)) {  //立体視かつサイドバイサイドまたはトップアンドボトムのとき
  1000:         frmFrame.setJMenuBar (null);  //メニューバーを表示しない
  1001:         Keyboard.kbdSetOn (false);  //キーボードを表示しない
  1002:       }
  1003:       pnlUpdateArrangement ();
  1004:     }
  1005:   }
  1006: 
  1007:   //  後始末
  1008:   public static void pnlTini () {
  1009:     //設定
  1010:     //  画面スケーリングモード
  1011:     Settings.sgsPutString ("scaling",
  1012:                            pnlFullscreenOn ? "fullscreen" :
  1013:                            pnlFitInWindowOn ? "fitinwindow" :
  1014:                            "fixedscale");
  1015:     //  固定倍率
  1016:     Settings.sgsPutInt ("fixedscale", pnlFixedScale);
  1017: 
  1018:     //  アスペクト比
  1019:     for (int key = 0; key < PNL_ASPECT_KEYS; key++) {
  1020:       String resolutionName = PNL_ASPECT_RESOLUTION_NAME[key];
  1021:       int value = pnlAspectMap[key];
  1022:       String screenName = PNL_ASPECT_SCREEN_NAME[value];
  1023:       Settings.sgsPutString ("aspectratio" + resolutionName, screenName);
  1024:     }
  1025: 
  1026:     //  補間アルゴリズム
  1027:     Settings.sgsPutString ("interpolation",
  1028:                            pnlInterpolation == RenderingHints.VALUE_INTERPOLATION_NEAREST_NEIGHBOR ? "nearest" :
  1029:                            pnlInterpolation == RenderingHints.VALUE_INTERPOLATION_BILINEAR ? "bilinear" :
  1030:                            pnlInterpolation == RenderingHints.VALUE_INTERPOLATION_BICUBIC ? "bicubic" :
  1031:                            "bilinear");
  1032:     //  立体視
  1033:     Settings.sgsPutOnOff ("stereoscopic", pnlStereoscopicOn);
  1034:     Settings.sgsPutString ("stereoscopicmethod",
  1035:                            pnlStereoscopicMethod == PNL_NAKED_EYE_CROSSING ? "nakedeyecrossing" :
  1036:                            pnlStereoscopicMethod == PNL_NAKED_EYE_PARALLEL ? "nakedeyeparallel" :
  1037:                            pnlStereoscopicMethod == PNL_SIDE_BY_SIDE ? "sidebyside" :
  1038:                            pnlStereoscopicMethod == PNL_TOP_AND_BOTTOM ? "topandbottom" :
  1039:                            "nakedeyecrossing");
  1040:   }
  1041: 
  1042:   //pnlUpdateAspectTable ()
  1043:   //  ピクセルアスペクト比テーブルを更新する
  1044:   public static void pnlUpdateAspectTable () {
  1045:     float[] ratio = new float[PNL_ASPECT_KEYS];  //[key]=pixelAspectRatio
  1046:     for (int key = 0; key < PNL_ASPECT_KEYS; key++) {
  1047:       int value = pnlAspectMap[key];
  1048:       ratio[key] = PNL_ASPECT_MATRIX[key][value];
  1049:     }
  1050:     pnlAspectTable[0] = ratio[0] * 2.0F;  //256x256*2
  1051:     pnlAspectTable[1] = ratio[2];         //512x512
  1052:     pnlAspectTable[2] = ratio[3];         //768x512
  1053:     pnlAspectTable[3] = ratio[3];         //
  1054:     pnlAspectTable[4] = ratio[1] * 4.0F;  //384x256*4
  1055:     pnlAspectTable[5] = ratio[1] * 2.0F;  //384x256*2
  1056:     pnlAspectTable[6] = ratio[3];         //
  1057:     pnlAspectTable[7] = ratio[3];         //
  1058:   }  //pnlUpdateAspectTable
  1059: 
  1060:   //pnlMake ()
  1061:   //  パネルを作る
  1062:   public static void pnlMake () {
  1063: 
  1064:     //パネル
  1065:     pnlPanel = new JPanel () {
  1066:       @Override protected void paintComponent (Graphics g) {
  1067:         Graphics2D g2 = (Graphics2D) g;
  1068:         if (PNL_FILL_BACKGROUND || pnlFillBackgroundRequest) {  //背景を塗り潰す
  1069:           if (!PNL_FILL_BACKGROUND) {
  1070:             pnlFillBackgroundRequest = false;
  1071:           }
  1072:           g2.setColor (Color.black);
  1073:           g2.fillRect (0, 0, pnlWidth, pnlHeight);
  1074:         }
  1075:         g2.setRenderingHint (RenderingHints.KEY_INTERPOLATION, pnlInterpolation);
  1076:         if (PNL_STEREOSCOPIC_ON && pnlStereoscopicOn) {  //立体視ON
  1077:           if (pnlStereoscopicMethod == PNL_NAKED_EYE_CROSSING) {
  1078:             g2.drawImage (pnlScreenImageRight,
  1079:                           pnlScreenX1, pnlScreenY1,
  1080:                           pnlScreenX2, pnlScreenY2,
  1081:                           0, 0, pnlScreenWidth, pnlScreenHeight,
  1082:                           null);
  1083:             g2.drawImage (pnlScreenImageLeft,
  1084:                           pnlScreenX3, pnlScreenY3,
  1085:                           pnlScreenX4, pnlScreenY4,
  1086:                           0, 0, pnlScreenWidth, pnlScreenHeight,
  1087:                           null);
  1088:           } else {
  1089:             //pnlStereoscopicMethod == PNL_NAKED_EYE_PARALLEL
  1090:             //pnlStereoscopicMethod == PNL_SIDE_BY_SIDE
  1091:             //pnlStereoscopicMethod == PNL_TOP_AND_BOTTOM
  1092:             g2.drawImage (pnlScreenImageLeft,
  1093:                           pnlScreenX1, pnlScreenY1,
  1094:                           pnlScreenX2, pnlScreenY2,
  1095:                           0, 0, pnlScreenWidth, pnlScreenHeight,
  1096:                           null);
  1097:             g2.drawImage (pnlScreenImageRight,
  1098:                           pnlScreenX3, pnlScreenY3,
  1099:                           pnlScreenX4, pnlScreenY4,
  1100:                           0, 0, pnlScreenWidth, pnlScreenHeight,
  1101:                           null);
  1102:           }
  1103:         } else {  //立体視OFF
  1104:           g2.drawImage (pnlScreenImageLeft,
  1105:                         pnlScreenX1, pnlScreenY1,
  1106:                         pnlScreenX2, pnlScreenY2,
  1107:                         0, 0, pnlScreenWidth, pnlScreenHeight,
  1108:                         null);
  1109:         }
  1110:         g2.drawImage (Keyboard.kbdImage, pnlKeyboardX, pnlKeyboardY, null);  //Graphics.drawImage()はimage==nullのとき何もしない
  1111:       }
  1112:       @Override protected void paintBorder (Graphics g) {
  1113:       }
  1114:       @Override protected void paintChildren (Graphics g) {
  1115:       }
  1116:     };
  1117:     pnlPanel.setBackground (Color.black);
  1118:     pnlPanel.setOpaque (true);
  1119:     pnlPanel.setPreferredSize (pnlSize);
  1120: 
  1121:     if (Mouse.musCursorAvailable) {
  1122:       pnlPanel.setCursor (Mouse.musCursorArray[1]);  //矢印カーソルを表示する
  1123:     }
  1124: 
  1125:   }  //pnlMake()
  1126: 
  1127:   //pnlStart ()
  1128:   //  パネルの動作を開始する
  1129:   //  イベントリスナーを設定する
  1130:   public static void pnlStart () {
  1131: 
  1132:     //コンポーネントリスナー
  1133:     ComponentFactory.addListener (
  1134:       pnlPanel,
  1135:       new ComponentAdapter () {
  1136:         @Override public void componentResized (ComponentEvent ce) {
  1137:           pnlWidth = pnlPanel.getWidth ();
  1138:           pnlHeight = pnlPanel.getHeight ();
  1139:           pnlUpdateArrangement ();
  1140:         }
  1141:       });
  1142: 
  1143:   }  //pnlStart()
  1144: 
  1145:   //pnlExitFullScreen (dialog)
  1146:   //  ダイアログやサブウインドウを開く前に全画面表示を終了する
  1147:   //  macOSのとき全画面表示のままモーダルダイアログを開くと操作できなくなる
  1148:   //  Windowsでも全画面表示のままサブウインドウを開くとサブウインドウが見えないので全画面表示を終了しなければならなくなる
  1149:   public static void pnlExitFullScreen (boolean dialog) {
  1150:     if (prgIsMac || !dialog) {
  1151:       pnlSetFullscreenOn (false);
  1152:     }
  1153:   }
  1154: 
  1155:   //pnlSetFullscreenOn (on)
  1156:   //  全画面表示を設定する
  1157:   public static void pnlSetFullscreenOn (boolean on) {
  1158:     if (pnlIsFullscreenSupported && pnlFullscreenOn != on) {
  1159:       if (on) {  //OFF→ON
  1160:         pnlFullscreenOn = true;
  1161:         pnlPrevKeyboardOn = Keyboard.kbdImage != null;  //全画面表示に移行する前はキーボードを表示していたか
  1162:         pnlPrevFitInWindowOn = pnlFitInWindowOn;  //全画面表示に移行する前はウインドウに合わせていたか
  1163:         mnbFullscreenMenuItem.setSelected (true);
  1164:         frmSetFullscreenOn (true);  //全画面表示に移行する
  1165:         pnlSetFitInWindowOn (true);  //ウインドウに合わせる
  1166:         if (pnlStereoscopicOn && (pnlStereoscopicMethod == PNL_SIDE_BY_SIDE ||
  1167:                                   pnlStereoscopicMethod == PNL_TOP_AND_BOTTOM)) {  //立体視かつサイドバイサイドまたはトップアンドボトムのとき
  1168:           frmFrame.setJMenuBar (null);  //メニューバーを表示しない
  1169:           Keyboard.kbdSetOn (false);  //キーボードを表示しない
  1170:         }
  1171:       } else {  //ON→OFF
  1172:         pnlFullscreenOn = false;
  1173:         if (pnlPrevKeyboardOn) {  //全画面表示に移行する前はキーボードを表示していた
  1174:           Keyboard.kbdSetOn (true);  //キーボードを表示する
  1175:         }
  1176:         frmFrame.setJMenuBar (mnbMenuBar);  //メニューバーを表示する
  1177:         if (!pnlPrevFitInWindowOn) {  //全画面表示に移行する前はウインドウに合わせていなかった
  1178:           pnlSetFitInWindowOn (false);  //ウインドウに合わせない
  1179:         } else {  //全画面表示に移行する前はウインドウに合わせていた
  1180:           mnbFitInWindowMenuItem.setSelected (true);
  1181:         }
  1182:         frmSetFullscreenOn (false);  //全画面表示を解除する
  1183:       }
  1184:     }
  1185:   }  //pnlSetFullscreenOn(boolean)
  1186: 
  1187:   //pnlSetFitInWindowOn (mode)
  1188:   //  ウインドウに合わせるモードを設定する
  1189:   //  ウインドウに合わせるモードには全画面表示が含まれる
  1190:   public static void pnlSetFitInWindowOn (boolean on) {
  1191:     if (pnlIsFitInWindowSupported && pnlFitInWindowOn != on) {
  1192:       pnlFitInWindowOn = on;
  1193:       pnlUpdateArrangement ();  //スクリーンとキーボードの配置を再計算する
  1194:       if (!pnlFullscreenOn) {  //全画面表示でないとき
  1195:         if (on) {
  1196:           mnbFitInWindowMenuItem.setSelected (true);
  1197:         } else {
  1198:           mnbFixedScaleMenuItem.setSelected (true);
  1199:         }
  1200:       }
  1201:     }
  1202:   }  //pnlSetFitInWindowOn(boolean)
  1203: 
  1204:   //pnlUpdateArrangement ()
  1205:   //  スクリーンとキーボードの配置を再計算する
  1206:   //    リサイズ、最大化、全画面表示などの操作でパネルの大きさが変わったとき
  1207:   //    ウインドウに合わせるかどうかが変わったとき
  1208:   //    ウインドウに合わせないが固定倍率が変わったとき
  1209:   //    キーボードの有無または種類が変わったとき
  1210:   //    X68000の画面モードが変更されてスクリーンの大きさが変わったとき
  1211:   //    立体視のon/offが変わったとき
  1212:   //    アスペクト比が変わったとき
  1213:   public static void pnlUpdateArrangement () {
  1214:     pnlStretchMode = pnlAspectTable[CRTC.crtHRLCurr << 2 | CRTC.crtHResoCurr];
  1215:     pnlScreenWidth = Math.max (256, (CRTC.crtR03HDispEndCurr - CRTC.crtR02HBackEndCurr) << 3);
  1216:     pnlScreenHeight = Math.max (64, (CRTC.crtR07VDispEndCurr - CRTC.crtR06VBackEndCurr) << (CRTC.crtInterlace || CRTC.crtSlit ? 1 : 0));
  1217:     pnlStretchWidth = Math.round ((float) pnlScreenWidth * pnlStretchMode);
  1218:     if (RasterBreakPoint.RBP_ON) {
  1219:       //ラスタブレークポイントウインドウが開いていたら更新する
  1220:       if ((dbgVisibleMask & DBG_RBP_VISIBLE_MASK) != 0) {
  1221:         RasterBreakPoint.rbpUpdateFrame ();
  1222:       }
  1223:     }
  1224:     //
  1225:     pnlFixedScale = pnlFixedModel.getNumber ().intValue ();  //固定倍率
  1226:     //スクリーンとキーボードの配置を決める
  1227:     if (!pnlFitInWindowOn) {  //固定倍率のとき
  1228:       //配置の計算
  1229:       //perl optdiv.pl 32768 100
  1230:       //  x/100==x*5243>>>19 (0<=x<=43698) [32768*5243==171802624]
  1231:       //pnlZoomWidth = (pnlStretchWidth * pnlFixedScale + 50) / 100;
  1232:       //pnlZoomHeight = (pnlScreenHeight * pnlFixedScale + 50) / 100;
  1233:       pnlZoomWidth = (pnlStretchWidth * pnlFixedScale + 50) * 5243 >>> 19;
  1234:       pnlZoomHeight = (pnlScreenHeight * pnlFixedScale + 50) * 5243 >>> 19;
  1235:       int width = Math.max (Math.max (256, pnlZoomWidth * pnlStereoscopicFactor), Keyboard.kbdWidth);
  1236:       int height = Math.max (64, pnlZoomHeight) + Keyboard.kbdHeight;
  1237:       pnlScreenX1 = (width - pnlZoomWidth * pnlStereoscopicFactor) >> 1;
  1238:       pnlScreenY1 = (height - pnlZoomHeight - Keyboard.kbdHeight) >> 1;
  1239:       if (pnlWidth != width || pnlHeight != height) {  //パネルの大きさが合っていないとき
  1240:         pnlWidth = width;
  1241:         pnlHeight = height;
  1242:         pnlMinimumWidth = width;  //固定倍率では使わないがウインドウに合わせるモードに移行したとき最小サイズが変化したことを検知できるようにする
  1243:         pnlMinimumHeight = height;
  1244:         pnlSize.setSize (width, height);
  1245:         //最小サイズと最大サイズ
  1246:         frmMinimumSize.setSize (width + frmMarginWidth, height + frmMarginHeight);
  1247:         frmFrame.setMinimumSize (frmMinimumSize);
  1248:         frmFrame.setMaximumSize (frmMinimumSize);
  1249:         frmFrame.setPreferredSize (frmMinimumSize);
  1250:         frmFrame.setResizable (false);
  1251:         pnlPanel.setMinimumSize (pnlSize);
  1252:         pnlPanel.setMaximumSize (pnlSize);
  1253:         pnlPanel.setPreferredSize (pnlSize);
  1254:         frmFrame.pack ();
  1255:       }
  1256:     } else {  //ウインドウに合わせるとき
  1257:       //配置の計算
  1258:       if (pnlWidth * pnlScreenHeight >= (pnlHeight - Keyboard.kbdHeight) * (pnlStretchWidth * pnlStereoscopicFactor)) {  //ウインドウに合わせると上下に隙間ができないとき
  1259:         //パネルの下端にキーボード配置して残った部分にスクリーンを目一杯拡大する
  1260:         //    pnlScreenX1                                          pnlScreenX1            pnlScreenX1
  1261:         //    |pnlZoomWidth|    |pnlZoomWidth|  |pnlZoomWidth|    |pnlZoomWidth|        |pnlZoomWidth|
  1262:         //  +-+------------+-+  +------------+  +------------+  +-+------------+-+  +---+------------+---+ --
  1263:         //  | |            | |  |            |  |            |  | |            | |  |   |            |   |
  1264:         //  | |   screen   | |  |   screen   |  |   screen   |  | |   screen   | |  |   |   screen   |   | pnlZoomHeight
  1265:         //  | |            | |  |            |  |            |  | |            | |  |   |            |   |
  1266:         //  | +-+--------+-+ |  +-+--------+-+  +------------+  +-+------------+-+  | +-+------------+-+ | -- pnlKeyboardY
  1267:         //  |   |keyboard|   |  | |keyboard| |  |  keyboard  |  |    keyboard    |  | |    keyboard    | | kbdHeight
  1268:         //  +---+--------+---+  +-+--------+-+  +------------+  +----------------+  +-+----------------+-+ --
  1269:         //      |                 |                             |    kbdWidth    |    |    kbdWidth    |
  1270:         //      pnlKeyboardX      pnlKeyboardX                                        pnlKeyboardX
  1271:         pnlZoomHeight = pnlHeight - Keyboard.kbdHeight;
  1272:         pnlZoomWidth = (pnlZoomHeight * pnlStretchWidth + (pnlScreenHeight >> 1)) / pnlScreenHeight;
  1273:         if (pnlStereoscopicOn && pnlStereoscopicMethod == PNL_SIDE_BY_SIDE) {
  1274:           pnlScreenX1 = ((pnlWidth >> 1) - (pnlZoomWidth >> 1)) >> 1;
  1275:         } else {
  1276:           pnlScreenX1 = (pnlWidth - pnlZoomWidth * pnlStereoscopicFactor) >> 1;
  1277:         }
  1278:         pnlScreenY1 = 0;
  1279:       } else {  //ウインドウに合わせると上下に隙間ができるとき
  1280:         //左右が先につっかえたのだからスクリーンの幅がキーボードの幅よりも狭いということはない
  1281:         //  スクリーンの幅がキーボードの幅よりも狭かったらスクリーンの上と左右の両方に隙間があることになってしまうのでウインドウに合っていない
  1282:         //  |pnlZoomWidth|  |pnlZoomWidth|
  1283:         //  +------------+  +------------+
  1284:         //  |            |  |            |
  1285:         //  +------------+  +------------+ -- pnlScreenY1
  1286:         //  |            |  |            |
  1287:         //  |   screen   |  |   screen   | pnlZoomHeight
  1288:         //  |            |  |            |
  1289:         //  +-+--------+-+  +------------+ -- pnlKeyboardY
  1290:         //  | |keyboard| |  |  keyboard  | kbdHeight
  1291:         //  | +--------+ |  +------------+ --
  1292:         //  |            |  |            |
  1293:         //  +------------+  +------------+
  1294:         //    |kbdWidth|    |  kbdWidth  |
  1295:         //    pnlKeyboardX
  1296:         pnlZoomWidth = pnlWidth / pnlStereoscopicFactor;
  1297:         pnlZoomHeight = (pnlZoomWidth * pnlStereoscopicFactor * pnlScreenHeight + (pnlStretchWidth * pnlStereoscopicFactor >> 1)) / (pnlStretchWidth * pnlStereoscopicFactor);
  1298:         pnlScreenX1 = 0;
  1299:         if (pnlStereoscopicOn && pnlStereoscopicMethod == PNL_TOP_AND_BOTTOM) {
  1300:           pnlScreenY1 = (((pnlHeight - Keyboard.kbdHeight) >> 1) - (pnlZoomHeight >> 1)) >> 1;
  1301:         } else {
  1302:           pnlScreenY1 = (pnlHeight - pnlZoomHeight - Keyboard.kbdHeight) >> 1;
  1303:         }
  1304:       }
  1305:       //最小サイズと最大サイズ
  1306:       int minimumWidth = Math.max (256, Keyboard.kbdWidth);
  1307:       int minimumHeight = 64 + Keyboard.kbdHeight;
  1308:       if (pnlMinimumWidth != minimumWidth || pnlMinimumHeight != minimumHeight) {  //最小サイズが変化した。ウインドウに合わせるモードに移行したかキーボードの有無または種類が変わった
  1309:         pnlMinimumWidth = minimumWidth;
  1310:         pnlMinimumHeight = minimumHeight;
  1311:         frmMinimumSize.setSize (minimumWidth + frmMarginWidth, minimumHeight + frmMarginHeight);
  1312:         frmFrame.setMinimumSize (frmMinimumSize);
  1313:         frmFrame.setMaximumSize (null);
  1314:         frmFrame.setResizable (true);
  1315:       }
  1316:     }
  1317:     pnlArrangementCommon ();
  1318:     Mouse.musUpdateSpeedRatio ();
  1319:     if (!PNL_FILL_BACKGROUND) {
  1320:       pnlFillBackgroundRequest = true;
  1321:     }
  1322:     pnlPanel.repaint ();
  1323:   }  //pnlUpdateArrangement()
  1324: 
  1325:   public static void pnlArrangementCommon () {
  1326:     if (PNL_STEREOSCOPIC_ON && pnlStereoscopicOn) {
  1327:       if (pnlStereoscopicMethod == PNL_NAKED_EYE_CROSSING ||
  1328:           pnlStereoscopicMethod == PNL_NAKED_EYE_PARALLEL) {
  1329:         pnlScreenX2 = pnlScreenX1 + pnlZoomWidth;
  1330:         pnlScreenX3 = pnlScreenX2;
  1331:         pnlScreenX4 = pnlScreenX3 + pnlZoomWidth;
  1332:         pnlScreenY2 = pnlScreenY1 + pnlZoomHeight;
  1333:         pnlScreenY3 = pnlScreenY1;
  1334:         pnlScreenY4 = pnlScreenY2;
  1335:       } else if (pnlStereoscopicMethod == PNL_SIDE_BY_SIDE) {
  1336:         pnlScreenX2 = pnlScreenX1 + (pnlZoomWidth >> 1);
  1337:         pnlScreenX3 = pnlScreenX1 + (pnlWidth >> 1);
  1338:         pnlScreenX4 = pnlScreenX3 + (pnlZoomWidth >> 1);
  1339:         pnlScreenY2 = pnlScreenY1 + pnlZoomHeight;
  1340:         pnlScreenY3 = pnlScreenY1;
  1341:         pnlScreenY4 = pnlScreenY2;
  1342:       } else {  //pnlStereoscopicMethod == PNL_TOP_AND_BOTTOM
  1343:         pnlScreenX2 = pnlScreenX1 + pnlZoomWidth;
  1344:         pnlScreenX3 = pnlScreenX1;
  1345:         pnlScreenX4 = pnlScreenX2;
  1346:         pnlScreenY2 = pnlScreenY1 + (pnlZoomHeight >> 1);
  1347:         pnlScreenY3 = pnlScreenY1 + ((pnlHeight - Keyboard.kbdHeight) >> 1);
  1348:         pnlScreenY4 = pnlScreenY3 + (pnlZoomHeight >> 1);
  1349:       }
  1350:     } else {
  1351:       pnlScreenX2 = pnlScreenX1 + pnlZoomWidth;
  1352:       pnlScreenX3 = pnlScreenX1;
  1353:       pnlScreenX4 = pnlScreenX2;
  1354:       pnlScreenY2 = pnlScreenY1 + pnlZoomHeight;
  1355:       pnlScreenY3 = pnlScreenY1;
  1356:       pnlScreenY4 = pnlScreenY2;
  1357:     }
  1358:     pnlKeyboardX = (pnlWidth - Keyboard.kbdWidth) >> 1;
  1359:     pnlKeyboardY = pnlScreenY4;
  1360:     pnlZoomRatioOut = (pnlZoomHeight << 16) / pnlScreenHeight;
  1361:     pnlZoomRatioInX = (pnlScreenWidth << 16) / (pnlZoomWidth * pnlStereoscopicFactor);
  1362:     pnlZoomRatioInY = (pnlScreenHeight << 16) / pnlZoomHeight;
  1363:   }
  1364: 
  1365: 
  1366: 
  1367:   //========================================================================================
  1368:   //$$RBT ロボット
  1369: 
  1370:   public static Robot rbtRobot;  //ロボット
  1371: 
  1372:   //rbtInit ()
  1373:   public static void rbtInit () {
  1374: 
  1375:     //ロボット
  1376:     rbtRobot = null;
  1377:     try {
  1378:       rbtRobot = new Robot ();  //プライマリスクリーンのみを対象とする
  1379:     } catch (Exception e) {
  1380:     }
  1381: 
  1382:   }  //rbtInit()
  1383: 
  1384: 
  1385: 
  1386:   //========================================================================================
  1387:   //$$MNB メニューバー
  1388:   //  メニューバーの高さは23px
  1389: 
  1390:   public static final int MNB_MODIFIERS = InputEvent.ALT_DOWN_MASK | InputEvent.SHIFT_DOWN_MASK;  //アクセラレータのモディファイヤ
  1391: 
  1392:   //メニューバー
  1393:   public static JMenuBar mnbMenuBar;  //メニューバー
  1394: 
  1395:   //メニュー
  1396:   public static JMenu mnbFileMenu;  //ファイル
  1397:   public static JMenu mnbDisplayMenu;  //画面
  1398:   public static JMenu mnbSoundMenu;  //音声
  1399:   public static JMenu mnbInputMenu;  //入力
  1400:   public static JMenu mnbConfigMenu;  //設定
  1401:   public static JMenu mnbLanguageMenu;  //言語
  1402: 
  1403:   //メニューアイテム
  1404:   //  チェックボックスなどの変更内容はアクションイベントから取り出せるので個々のメニューアイテムに名前を付ける必要はない
  1405:   //  メニュー以外の方法で変更できるアイテムと一時的に変更できなくなるアイテムに名前をつけておく
  1406:   //  最初から最後まで選択できないメニューアイテムはメニューバーを作る時点で無効化するか、表示しない
  1407:   public static JMenuItem mnbQuitMenuItem;  //終了
  1408:   public static JRadioButtonMenuItem mnbFullscreenMenuItem;  //全画面表示
  1409:   public static JRadioButtonMenuItem mnbFitInWindowMenuItem;  //ウインドウに合わせる
  1410:   public static JRadioButtonMenuItem mnbFixedScaleMenuItem;  //固定倍率
  1411:   public static JCheckBoxMenuItem mnbStereoscopicMenuItem;  //立体視
  1412:   public static JCheckBoxMenuItem mnbPlayMenuItem;  //音声出力
  1413:   public static JMenuItem mnbPasteMenuItem;  //貼り付け
  1414:   public static JRadioButtonMenuItem mnbStandardKeyboardMenuItem;  //標準キーボード
  1415:   public static JRadioButtonMenuItem mnbCompactKeyboardMenuItem;  //コンパクトキーボード
  1416:   public static JRadioButtonMenuItem mnbNoKeyboardMenuItem;  //キーボードなし
  1417:   public static JLabel mnbVolumeLabel;  //音量
  1418: 
  1419: 
  1420:   //フォントサイズメニュー
  1421: 
  1422:   //mnbMakeFontSizeMenu ()
  1423:   //  フォントサイズメニューを作る
  1424:   public static JMenu mnbMakeFontSizeMenu () {
  1425:     //  アクションリスナー
  1426:     ActionListener actionListener = new ActionListener () {
  1427:       @Override public void actionPerformed (ActionEvent ae) {
  1428:         String command = ae.getActionCommand ();
  1429:         switch (command) {
  1430:         case "Very small":  //極小
  1431:           LnF.lnfFontSizeRequest = 10;
  1432:           break;
  1433:         case "Small":  //小
  1434:           LnF.lnfFontSizeRequest = 12;
  1435:           break;
  1436:         case "Medium":  //中
  1437:           LnF.lnfFontSizeRequest = 14;
  1438:           break;
  1439:         case "Large":  //大
  1440:           LnF.lnfFontSizeRequest = 16;
  1441:           break;
  1442:         case "Very large":  //極大
  1443:           LnF.lnfFontSizeRequest = 18;
  1444:           break;
  1445:         default:
  1446:           System.out.println ("unknown action command " + command);
  1447:         }
  1448:       }
  1449:     };
  1450:     //  ボタングループ
  1451:     ButtonGroup fontSizeGroup = new ButtonGroup ();
  1452:     //  メニュー
  1453:     return Multilingual.mlnText (
  1454:       ComponentFactory.createMenu (
  1455:         "Font size",
  1456:         Multilingual.mlnText (
  1457:           ComponentFactory.pointSize (
  1458:             ComponentFactory.createRadioButtonMenuItem (fontSizeGroup, LnF.lnfFontSizeRequest == 10, "Very small", actionListener),
  1459:             10),
  1460:           "ja", "極小"),
  1461:         Multilingual.mlnText (
  1462:           ComponentFactory.pointSize (
  1463:             ComponentFactory.createRadioButtonMenuItem (fontSizeGroup, LnF.lnfFontSizeRequest == 12, "Small", actionListener),
  1464:             12),
  1465:           "ja", "小"),
  1466:         Multilingual.mlnText (
  1467:           ComponentFactory.pointSize (
  1468:             ComponentFactory.createRadioButtonMenuItem (fontSizeGroup, LnF.lnfFontSizeRequest == 14, "Medium", actionListener),
  1469:             14),
  1470:           "ja", "中"),
  1471:         Multilingual.mlnText (
  1472:           ComponentFactory.pointSize (
  1473:             ComponentFactory.createRadioButtonMenuItem (fontSizeGroup, LnF.lnfFontSizeRequest == 16, "Large", actionListener),
  1474:             16),
  1475:           "ja", "大"),
  1476:         Multilingual.mlnText (
  1477:           ComponentFactory.pointSize (
  1478:             ComponentFactory.createRadioButtonMenuItem (fontSizeGroup, LnF.lnfFontSizeRequest == 18, "Very large", actionListener),
  1479:             18),
  1480:           "ja", "極大")),
  1481:       "ja", "フォントサイズ");
  1482:   }  //mnbMakeFontSizeMenu
  1483: 
  1484: 
  1485:   //色メニュー
  1486:   public static final DecimalSpinner[] mnbColorSpinners = new DecimalSpinner[9];  //スピナー
  1487:   public static final int[] mnbColorRGB = new int[15];
  1488:   public static JPanel mnbColorPanel;
  1489: 
  1490:   //mnbColorHSBToRGB ()
  1491:   //  LnF.lnfHSBからmnbColorRGBを作る
  1492:   public static void mnbColorHSBToRGB () {
  1493:     for (int i = 0; i <= 14; i++) {
  1494:       int[] t = LnF.LNF_HSB_INTERPOLATION_TABLE[i];
  1495:       float h = (float) (t[0] * LnF.lnfHSB[0] + t[1] * LnF.lnfHSB[1] + t[2] * LnF.lnfHSB[2]) / (49.0F * 360.0F);
  1496:       float s = (float) (t[0] * LnF.lnfHSB[3] + t[1] * LnF.lnfHSB[4] + t[2] * LnF.lnfHSB[5]) / (49.0F * 100.0F);
  1497:       float b = (float) (t[0] * LnF.lnfHSB[6] + t[1] * LnF.lnfHSB[7] + t[2] * LnF.lnfHSB[8]) / (49.0F * 100.0F);
  1498:       mnbColorRGB[i] = Color.HSBtoRGB (h,
  1499:                                        Math.max (0.0F, Math.min (1.0F, s)),
  1500:                                        Math.max (0.0F, Math.min (1.0F, b)));
  1501:     }
  1502:   }  //mnbColorHSBToRGB
  1503: 
  1504:   //mnbMakeColorMenu ()
  1505:   //  色メニューを作る
  1506:   public static JMenu mnbMakeColorMenu () {
  1507:     mnbColorHSBToRGB ();
  1508:     //  パネル
  1509:     mnbColorPanel = ComponentFactory.setColor (
  1510:       ComponentFactory.setFixedSize (
  1511:         new JPanel () {
  1512:           @Override protected void paintComponent (Graphics g) {
  1513:             super.paintComponent (g);
  1514:             for (int i = 0; i <= 14; i++) {
  1515:               g.setColor (new Color (mnbColorRGB[i]));
  1516:               g.fillRect (LnF.lnfFontSize * i, 0, LnF.lnfFontSize, LnF.lnfFontSize * 5);
  1517:             }
  1518:           }
  1519:         },
  1520:         LnF.lnfFontSize * 15, LnF.lnfFontSize * 5),
  1521:       Color.white, Color.black);
  1522:     //  チェンジリスナー
  1523:     ChangeListener changeListener = new ChangeListener () {
  1524:       @Override public void stateChanged (ChangeEvent ce) {
  1525:         DecimalSpinner spinner = (DecimalSpinner) ce.getSource ();
  1526:         LnF.lnfHSB[spinner.getOption ()] = spinner.getIntValue ();
  1527:         mnbColorHSBToRGB ();
  1528:         mnbColorPanel.repaint ();
  1529:       }
  1530:     };
  1531:     //  アクションリスナー
  1532:     ActionListener actionListener = new ActionListener () {
  1533:       @Override public void actionPerformed (ActionEvent ae) {
  1534:         String command = ae.getActionCommand ();
  1535:         switch (command) {
  1536:         case "Reset to default values":  //初期値に戻す
  1537:           for (int i = 0; i < 9; i++) {
  1538:             LnF.lnfHSB[i] = LnF.LNF_DEFAULT_HSB[i];
  1539:             mnbColorSpinners[i].setIntValue (LnF.lnfHSB[i]);
  1540:           }
  1541:           mnbColorHSBToRGB ();
  1542:           mnbColorPanel.repaint ();
  1543:           break;
  1544:         default:
  1545:           System.out.println ("unknown action command " + command);
  1546:         }
  1547:       }
  1548:     };
  1549:     //  スピナー
  1550:     for (int i = 0; i < 9; i++) {
  1551:       mnbColorSpinners[i] = ComponentFactory.createDecimalSpinner (
  1552:         LnF.lnfHSB[i], 0, i < 3 ? 720 : 100, 1, i, changeListener);
  1553:     }
  1554:     //  メニュー
  1555:     return Multilingual.mlnText (
  1556:       ComponentFactory.createMenu (
  1557:         "Color",
  1558:         ComponentFactory.createHorizontalBox (
  1559:           mnbColorSpinners[0],
  1560:           mnbColorSpinners[1],
  1561:           mnbColorSpinners[2],
  1562:           ComponentFactory.createLabel ("H °"),
  1563:           Box.createHorizontalGlue ()
  1564:           ),
  1565:         ComponentFactory.createHorizontalBox (
  1566:           mnbColorSpinners[3],
  1567:           mnbColorSpinners[4],
  1568:           mnbColorSpinners[5],
  1569:           ComponentFactory.createLabel ("S%"),
  1570:           Box.createHorizontalGlue ()
  1571:           ),
  1572:         ComponentFactory.createHorizontalBox (
  1573:           mnbColorSpinners[6],
  1574:           mnbColorSpinners[7],
  1575:           mnbColorSpinners[8],
  1576:           ComponentFactory.createLabel ("B%"),
  1577:           Box.createHorizontalGlue ()
  1578:           ),
  1579:         ComponentFactory.createHorizontalBox (
  1580:           ComponentFactory.setLineBorder (mnbColorPanel),
  1581:           Box.createHorizontalGlue ()
  1582:           ),
  1583:         Multilingual.mlnText (ComponentFactory.createMenuItem ("Reset to default values", actionListener), "ja", "初期値に戻す")
  1584:         ),
  1585:       "ja", "色");
  1586:   }  //mnbMakeColorMenu
  1587: 
  1588: 
  1589:   //言語メニュー
  1590:   //  テキストで書く
  1591:   //    国旗アイコンは対象とするマーケットを選択させるときに使うものであり、表示言語を切り替えるだけのメニューに国旗を用いるのは不適切
  1592:   public static JMenu mnbMakeLanguageMenu () {
  1593:     //  アクションリスナー
  1594:     ActionListener actionListener = new ActionListener () {
  1595:       @Override public void actionPerformed (ActionEvent ae) {
  1596:         String command = ae.getActionCommand ();
  1597:         switch (command) {
  1598:         case "English":
  1599:           Multilingual.mlnChange ("en");
  1600:           break;
  1601:         case "日本語":
  1602:           Multilingual.mlnChange ("ja");
  1603:           break;
  1604:         default:
  1605:           System.out.println ("unknown action command " + command);
  1606:         }
  1607:       }
  1608:     };
  1609:     //  ボタングループ
  1610:     ButtonGroup languageGroup = new ButtonGroup ();
  1611:     //  メニュー
  1612:     return mnbLanguageMenu = Multilingual.mlnText (
  1613:       ComponentFactory.createMenu (
  1614:         "Language", 'L',
  1615:         ComponentFactory.createRadioButtonMenuItem (languageGroup, Multilingual.mlnEnglish, "English", actionListener),
  1616:         ComponentFactory.createRadioButtonMenuItem (languageGroup, Multilingual.mlnJapanese, "日本語", actionListener),
  1617:         ComponentFactory.createHorizontalSeparator (),
  1618:         mnbMakeFontSizeMenu (),  //フォントサイズメニュー
  1619:         mnbMakeColorMenu ()  //色メニュー
  1620:         ),
  1621:       "ja", "言語");
  1622:   }  //mnbMakeLanguageMenu
  1623: 
  1624: 
  1625:   //mnbMakeMenu ()
  1626:   //  メニューバーを作る
  1627:   //  メニューバーの幅は狭くしたいがメニューの幅が狭すぎると隣のメニューに流れやすくなって操作しにくいのでメニューの数を必要最小限にする
  1628:   public static void mnbMakeMenu () {
  1629: 
  1630:     //アクションリスナー
  1631:     ActionListener listener = new ActionListener () {
  1632:       @Override public void actionPerformed (ActionEvent ae) {
  1633:         Object source = ae.getSource ();
  1634:         String command = ae.getActionCommand ();
  1635:         switch (command) {
  1636: 
  1637:           //ファイルメニュー
  1638:         case "Quit":  //終了
  1639:           prgTini ();
  1640:           break;
  1641: 
  1642:           //画面メニュー
  1643:         case "Full screen":  //全画面表示
  1644:           pnlSetFullscreenOn (true);
  1645:           break;
  1646:         case "Fit in window":  //ウインドウに合わせる
  1647:           if (pnlFullscreenOn) {  //全画面表示になっているとき
  1648:             pnlPrevFitInWindowOn = true;
  1649:             pnlSetFullscreenOn (false);
  1650:           } else {  //全画面表示になっていないとき
  1651:             pnlSetFitInWindowOn (true);
  1652:           }
  1653:           break;
  1654:         case "Fixed scale":  //固定倍率
  1655:           if (pnlFullscreenOn) {  //全画面表示になっているとき
  1656:             pnlPrevFitInWindowOn = false;
  1657:             pnlSetFullscreenOn (false);
  1658:           } else {  //全画面表示になっていないとき
  1659:             pnlSetFitInWindowOn (false);
  1660:           }
  1661:           break;
  1662:         case "50%":
  1663:         case "75%":
  1664:         case "100%":
  1665:         case "150%":
  1666:         case "200%":
  1667:           pnlFixedModel.setValue (Integer.valueOf (Integer.parseInt (command.substring (0, command.length () - 1))));  //pnlFixedSpinnerのChangeEventが発動する
  1668:           break;
  1669:         case "Nearest neighbor":  //最近傍補間
  1670:           pnlInterpolation = RenderingHints.VALUE_INTERPOLATION_NEAREST_NEIGHBOR;
  1671:           pnlPanel.repaint ();
  1672:           break;
  1673:         case "Bilinear":  //線形補間
  1674:           pnlInterpolation = RenderingHints.VALUE_INTERPOLATION_BILINEAR;
  1675:           pnlPanel.repaint ();
  1676:           break;
  1677:         case "Bicubic":  //三次補間
  1678:           pnlInterpolation = RenderingHints.VALUE_INTERPOLATION_BICUBIC;
  1679:           pnlPanel.repaint ();
  1680:           break;
  1681:           //
  1682:         case "Draw all changed pictures":  //変化した画像をすべて描画する
  1683:           if (CRTC.CRT_ENABLE_INTERMITTENT) {
  1684:             CRTC.crtIntermittentInterval = 0;
  1685:           }
  1686:           break;
  1687:         case "Draw a changed picture once every two times":  //変化した画像を 2 回に 1 回描画する
  1688:           if (CRTC.CRT_ENABLE_INTERMITTENT) {
  1689:             CRTC.crtIntermittentInterval = 1;
  1690:           }
  1691:           break;
  1692:         case "Draw a changed picture once every three times":  //変化した画像を 3 回に 1 回描画する
  1693:           if (CRTC.CRT_ENABLE_INTERMITTENT) {
  1694:             CRTC.crtIntermittentInterval = 2;
  1695:           }
  1696:           break;
  1697:         case "Draw a changed picture once every four times":  //変化した画像を 4 回に 1 回描画する
  1698:           if (CRTC.CRT_ENABLE_INTERMITTENT) {
  1699:             CRTC.crtIntermittentInterval = 3;
  1700:           }
  1701:           break;
  1702:         case "Draw a changed picture once every five times":  //変化した画像を 5 回に 1 回描画する
  1703:           if (CRTC.CRT_ENABLE_INTERMITTENT) {
  1704:             CRTC.crtIntermittentInterval = 4;
  1705:           }
  1706:           break;
  1707:           //
  1708:         case "Stereoscopic viewing":  //立体視
  1709:           pnlSetStereoscopic (((JCheckBoxMenuItem) source).isSelected (), pnlStereoscopicMethod);
  1710:           break;
  1711:         case "Naked-eye crossing":  //裸眼交差法
  1712:           pnlSetStereoscopic (pnlStereoscopicOn, PNL_NAKED_EYE_CROSSING);
  1713:           break;
  1714:         case "Naked-eye parallel":  //裸眼平行法
  1715:           pnlSetStereoscopic (pnlStereoscopicOn, PNL_NAKED_EYE_PARALLEL);
  1716:           break;
  1717:         case "Side-by-side":  //サイドバイサイド
  1718:           pnlSetStereoscopic (pnlStereoscopicOn, PNL_SIDE_BY_SIDE);
  1719:           break;
  1720:         case "Top-and-bottom":  //トップアンドボトム
  1721:           pnlSetStereoscopic (pnlStereoscopicOn, PNL_TOP_AND_BOTTOM);
  1722:           break;
  1723:           //
  1724:         case "Sprite pattern viewer":  //スプライトパターンビュア
  1725:           if (SpritePatternViewer.SPV_ON) {
  1726:             SpritePatternViewer.spvOpen ();
  1727:           }
  1728:           break;
  1729:         case "Screen mode test":  //表示モードテスト
  1730:           if (ScreenModeTest.SMT_ON) {
  1731:             ScreenModeTest.smtOpen ();
  1732:           }
  1733:           break;
  1734: 
  1735:           //音声メニュー
  1736:         case "Play":  //音声出力
  1737:           SoundSource.sndSetPlayOn (((JCheckBoxMenuItem) source).isSelected ());
  1738:           break;
  1739:         case "OPM output":  //OPM出力
  1740:           OPM.opmSetOutputOn (((JCheckBoxMenuItem) source).isSelected ());
  1741:           break;
  1742:         case "OPM log":  //OPM ログ
  1743:           OPMLog.olgOpen ();
  1744:           break;
  1745:           //
  1746:         case "PCM output":  //PCM出力
  1747:           ADPCM.pcmSetOutputOn (((JCheckBoxMenuItem) source).isSelected ());
  1748:           break;
  1749:         case "Sound thinning":  //音声 間引き
  1750:           SoundSource.sndRateConverter = SoundSource.SND_CHANNELS == 1 ? SoundSource.SNDRateConverter.THINNING_MONO : SoundSource.SNDRateConverter.THINNING_STEREO;
  1751:           break;
  1752:         case "Sound linear interpolation":  //音声 線形補間
  1753:           SoundSource.sndRateConverter = SoundSource.SND_CHANNELS == 1 ? SoundSource.SNDRateConverter.LINEAR_MONO : SoundSource.SNDRateConverter.LINEAR_STEREO;
  1754:           break;
  1755:         case "Sound piecewise-constant area interpolation":  //音声 区分定数面積補間
  1756:           SoundSource.sndRateConverter = SoundSource.SNDRateConverter.CONSTANT_AREA_STEREO_48000;
  1757:           break;
  1758:         case "Sound linear area interpolation":  //音声 線形面積補間
  1759:           SoundSource.sndRateConverter = SoundSource.SNDRateConverter.LINEAR_AREA_STEREO_48000;
  1760:           break;
  1761:         case "Sound monitor":  //音声モニタ
  1762:           SoundMonitor.smnOpen ();
  1763:           break;
  1764:         case "PCM piecewise-constant interpolation":  //PCM 区分定数補間
  1765:           ADPCM.pcmSetInterpolationAlgorithm (ADPCM.PCM_INTERPOLATION_CONSTANT);
  1766:           break;
  1767:         case "PCM linear interpolation":  //PCM 線形補間
  1768:           ADPCM.pcmSetInterpolationAlgorithm (ADPCM.PCM_INTERPOLATION_LINEAR);
  1769:           break;
  1770:         case "PCM hermite interpolation":  //PCM エルミート補間
  1771:           ADPCM.pcmSetInterpolationAlgorithm (ADPCM.PCM_INTERPOLATION_HERMITE);
  1772:           break;
  1773:         case "PCM 8MHz/4MHz":
  1774:           ADPCM.pcmOSCFreqRequest = 0;
  1775:           break;
  1776:         case "PCM 8MHz/16MHz":
  1777:           ADPCM.pcmOSCFreqRequest = 1;
  1778:           break;
  1779: 
  1780:           //入力メニュー
  1781:         case "Paste":  //貼り付け
  1782:           CONDevice.conDoPaste ();
  1783:           break;
  1784:         case "No keyboard":  //キーボードなし
  1785:           Keyboard.kbdSetOn (false);
  1786:           break;
  1787:         case "Standard keyboard":  //標準キーボード
  1788:           Keyboard.kbdSetType (Keyboard.KBD_STANDARD_TYPE);
  1789:           Keyboard.kbdSetOn (true);
  1790:           break;
  1791:         case "Compact keyboard":  //コンパクトキーボード
  1792:           Keyboard.kbdSetType (Keyboard.KBD_COMPACT_TYPE);
  1793:           Keyboard.kbdSetOn (true);
  1794:           break;
  1795:         case "Key assignments":  //キー割り当て
  1796:           Keyboard.kbdOpen ();
  1797:           break;
  1798:         case "Joystick port settings":  //ジョイスティックポート設定
  1799:           PPI.ppiOpen ();
  1800:           break;
  1801: 
  1802:           //設定メニュー
  1803:         case "RS-232C and terminal":  //RS-232C とターミナル
  1804:           RS232CTerminal.trmOpen ();
  1805:           break;
  1806:           //  デバッグ
  1807:         case "Console":  //コンソール
  1808:           DebugConsole.dgtOpen ();
  1809:           break;
  1810:         case "Register list":  //レジスタ
  1811:           RegisterList.drpOpen ();
  1812:           break;
  1813:         case "Disassemble list":  //逆アセンブルリスト
  1814:           DisassembleList.ddpOpen (-1, -1, true);
  1815:           break;
  1816:         case "Memory dump list":  //メモリダンプリスト
  1817:           MemoryDumpList.dmpOpen (-1, -1, true);
  1818:           break;
  1819:         case "Logical space monitor":  //論理空間モニタ
  1820:           LogicalSpaceMonitor.atwOpen ();
  1821:           break;
  1822:         case "Physical space monitor":  //物理空間モニタ
  1823:           PhysicalSpaceMonitor.paaOpen ();
  1824:           break;
  1825:         case "Address translation caches monitor":  //アドレス変換キャッシュモニタ
  1826:           if (ATCMonitor.ACM_ON) {
  1827:             ATCMonitor.acmOpen ();
  1828:           }
  1829:           break;
  1830:         case "Branch log":  //分岐ログ
  1831:           if (BranchLog.BLG_ON) {
  1832:             BranchLog.blgOpen (BranchLog.BLG_SELECT_NONE);
  1833:           }
  1834:           break;
  1835:         case "Program flow visualizer":  //プログラムフロービジュアライザ
  1836:           if (ProgramFlowVisualizer.PFV_ON) {
  1837:             ProgramFlowVisualizer.pfvOpen ();
  1838:           }
  1839:           break;
  1840:         case "Raster break point":  //ラスタブレークポイント
  1841:           if (RasterBreakPoint.RBP_ON) {
  1842:             RasterBreakPoint.rbpOpen ();
  1843:           }
  1844:           break;
  1845:         case "Data break point":  //データブレークポイント
  1846:           if (DataBreakPoint.DBP_ON) {
  1847:             DataBreakPoint.dbpOpen ();
  1848:           }
  1849:           break;
  1850:         case "Root pointer list":  //ルートポインタリスト
  1851:           if (RootPointerList.RTL_ON) {
  1852:             RootPointerList.rtlOpen ();
  1853:           }
  1854:           break;
  1855:           //  起動デバイス
  1856:           //  RTC
  1857:         case "Adjust clock to host":  //時計をホストに合わせる
  1858:           RP5C15.rtcSetByHost ();
  1859:           break;
  1860:           //  SRAM
  1861:           //  設定ファイル
  1862:           //
  1863:         case "Printer":  //プリンタ
  1864:           PrinterPort.prnOpen ();
  1865:           break;
  1866:           //
  1867:         case "Mouse button status":  //マウスのボタンの状態
  1868:           Mouse.musOutputButtonStatus = ((JCheckBoxMenuItem) source).isSelected ();
  1869:           break;
  1870:           //
  1871:         case "Java runtime environment information":
  1872:           prgOpenJavaDialog ();
  1873:           break;
  1874:         case "Version information":
  1875:           prgOpenAboutDialog ();
  1876:           break;
  1877:         case "XEiJ License":
  1878:           prgOpenXEiJLicenseDialog ();
  1879:           break;
  1880:         case "FSHARP License":
  1881:           prgOpenSHARPLicenseDialog ();
  1882:           break;
  1883:         case "ymfm License":
  1884:           prgOpenYmfmLicenseDialog ();
  1885:           break;
  1886:         case "jSerialComm License":
  1887:           prgOpenJSerialCommLicenseDialog ();
  1888:           break;
  1889: 
  1890:         default:
  1891:           System.out.println ("unknown action command " + command);
  1892: 
  1893:         }
  1894:       }
  1895:     };
  1896: 
  1897:     //  メインメモリ
  1898:     ActionListener mainMemoryListener = new ActionListener () {
  1899:       @Override public void actionPerformed (ActionEvent ae) {
  1900:         Object source = ae.getSource ();
  1901:         String command = ae.getActionCommand ();
  1902:         switch (command) {
  1903:         case "1MB":
  1904:           MainMemory.mmrMemorySizeRequest = 0x00100000;
  1905:           break;
  1906:         case "2MB":
  1907:           MainMemory.mmrMemorySizeRequest = 0x00200000;
  1908:           break;
  1909:         case "4MB":
  1910:           MainMemory.mmrMemorySizeRequest = 0x00400000;
  1911:           break;
  1912:         case "6MB":
  1913:           MainMemory.mmrMemorySizeRequest = 0x00600000;
  1914:           break;
  1915:         case "8MB":
  1916:           MainMemory.mmrMemorySizeRequest = 0x00800000;
  1917:           break;
  1918:         case "10MB":
  1919:           MainMemory.mmrMemorySizeRequest = 0x00a00000;
  1920:           break;
  1921:         case "12MB":
  1922:           MainMemory.mmrMemorySizeRequest = 0x00c00000;
  1923:           break;
  1924:         case "Save contents on exit":  //終了時に内容を保存する
  1925:           MainMemory.mmrMemorySaveOn = ((JCheckBoxMenuItem) source).isSelected ();
  1926:           break;
  1927:         }
  1928:       }
  1929:     };
  1930:     ButtonGroup mainMemoryGroup = new ButtonGroup ();
  1931:     JMenu mainMemoryMenu = Multilingual.mlnText (
  1932:       ComponentFactory.createMenu (
  1933:         "Main memory",
  1934:         Multilingual.mlnText (
  1935:           ComponentFactory.createRadioButtonMenuItem (mainMemoryGroup, MainMemory.mmrMemorySizeRequest == 0x00100000, "1MB", mainMemoryListener),
  1936:           "ja", "1MB"),
  1937:         Multilingual.mlnText (
  1938:           ComponentFactory.createRadioButtonMenuItem (mainMemoryGroup, MainMemory.mmrMemorySizeRequest == 0x00200000, "2MB", mainMemoryListener),
  1939:           "ja", "2MB"),
  1940:         Multilingual.mlnText (
  1941:           ComponentFactory.createRadioButtonMenuItem (mainMemoryGroup, MainMemory.mmrMemorySizeRequest == 0x00400000, "4MB", mainMemoryListener),
  1942:           "ja", "4MB"),
  1943:         Multilingual.mlnText (
  1944:           ComponentFactory.createRadioButtonMenuItem (mainMemoryGroup, MainMemory.mmrMemorySizeRequest == 0x00600000, "6MB", mainMemoryListener),
  1945:           "ja", "6MB"),
  1946:         Multilingual.mlnText (
  1947:           ComponentFactory.createRadioButtonMenuItem (mainMemoryGroup, MainMemory.mmrMemorySizeRequest == 0x00800000, "8MB", mainMemoryListener),
  1948:           "ja", "8MB"),
  1949:         Multilingual.mlnText (
  1950:           ComponentFactory.createRadioButtonMenuItem (mainMemoryGroup, MainMemory.mmrMemorySizeRequest == 0x00a00000, "10MB", mainMemoryListener),
  1951:           "ja", "10MB"),
  1952:         Multilingual.mlnText (
  1953:           ComponentFactory.createRadioButtonMenuItem (mainMemoryGroup, MainMemory.mmrMemorySizeRequest == 0x00c00000, "12MB", mainMemoryListener),
  1954:           "ja", "12MB"),
  1955:         ComponentFactory.createHorizontalSeparator (),
  1956:         Multilingual.mlnText (
  1957:           ComponentFactory.createCheckBoxMenuItem (MainMemory.mmrMemorySaveOn, "Save contents on exit", mainMemoryListener),
  1958:           "ja", "終了時に内容を保存する"),
  1959:         SRAM.smrModifyMemorySizeMenuItem
  1960:         ),
  1961:       "ja", "メインメモリ");
  1962: 
  1963:     //  X68030/Xellent30 のハイメモリ
  1964:     ActionListener highMemoryListener = new ActionListener () {
  1965:       @Override public void actionPerformed (ActionEvent ae) {
  1966:         Object source = ae.getSource ();
  1967:         String command = ae.getActionCommand ();
  1968:         switch (command) {
  1969:         case "None":  //なし
  1970:           busHighMemorySize = 0 << 20;
  1971:           break;
  1972:         case "16MB":
  1973:           busHighMemorySize = 16 << 20;
  1974:           break;
  1975:         case "Save contents on exit":  //終了時に内容を保存する
  1976:           busHighMemorySaveOn = ((JCheckBoxMenuItem) source).isSelected ();
  1977:           break;
  1978:         }
  1979:       }
  1980:     };
  1981:     ButtonGroup highMemoryGroup = new ButtonGroup ();
  1982:     JMenu highMemoryMenu = Multilingual.mlnText (
  1983:       ComponentFactory.createMenu (
  1984:         "High memory on X68030/Xellent30",
  1985:         Multilingual.mlnText (
  1986:           ComponentFactory.createRadioButtonMenuItem (highMemoryGroup, busHighMemorySize == 0 << 20, "None", highMemoryListener),
  1987:           "ja", "なし"),
  1988:         Multilingual.mlnText (
  1989:           ComponentFactory.createRadioButtonMenuItem (highMemoryGroup, busHighMemorySize == 16 << 20, "16MB", highMemoryListener),
  1990:           "ja", "16MB"),
  1991:         ComponentFactory.createHorizontalSeparator (),
  1992:         Multilingual.mlnText (
  1993:           ComponentFactory.createCheckBoxMenuItem (busHighMemorySaveOn, "Save contents on exit", highMemoryListener),
  1994:           "ja", "終了時に内容を保存する")
  1995:         ),
  1996:       "ja", "X68030/Xellent30 のハイメモリ");
  1997: 
  1998:     //  060turbo のハイメモリ
  1999:     ActionListener localMemoryListener = new ActionListener () {
  2000:       @Override public void actionPerformed (ActionEvent ae) {
  2001:         Object source = ae.getSource ();
  2002:         String command = ae.getActionCommand ();
  2003:         switch (command) {
  2004:         case "None":  //なし
  2005:           busLocalMemorySize = 0 << 20;
  2006:           break;
  2007:         case "16MB":
  2008:           busLocalMemorySize = 16 << 20;
  2009:           break;
  2010:         case "32MB":
  2011:           busLocalMemorySize = 32 << 20;
  2012:           break;
  2013:         case "64MB":
  2014:           busLocalMemorySize = 64 << 20;
  2015:           break;
  2016:         case "128MB":
  2017:           busLocalMemorySize = 128 << 20;
  2018:           break;
  2019:         case "256MB":
  2020:           busLocalMemorySize = 256 << 20;
  2021:           break;
  2022:         case "384MB":
  2023:           busLocalMemorySize = 384 << 20;
  2024:           break;
  2025:         case "512MB":
  2026:           busLocalMemorySize = 512 << 20;
  2027:           break;
  2028:         case "768MB":
  2029:           busLocalMemorySize = 768 << 20;
  2030:           break;
  2031:         case "Save contents on exit":  //終了時に内容を保存する
  2032:           busLocalMemorySaveOn = ((JCheckBoxMenuItem) source).isSelected ();
  2033:           break;
  2034:         case "Available on X68000":  //X68000 でも有効
  2035:           busHimem68000 = ((JCheckBoxMenuItem) source).isSelected ();
  2036:           break;
  2037:         case "Available on X68030/Xellent30":  //X68030/Xellent30 でも有効
  2038:           busHighMemory060turboOn = ((JCheckBoxMenuItem) source).isSelected ();
  2039:           break;
  2040:         }
  2041:       }
  2042:     };
  2043:     ButtonGroup localMenoryGroup = new ButtonGroup ();
  2044:     JMenu localMemoryMenu = Multilingual.mlnText (
  2045:       ComponentFactory.createMenu (
  2046:         "High memory on 060turbo",
  2047:         Multilingual.mlnText (
  2048:           ComponentFactory.createRadioButtonMenuItem (localMenoryGroup, busLocalMemorySize == 0 << 20, "None", localMemoryListener),
  2049:           "ja", "なし"),
  2050:         ComponentFactory.createRadioButtonMenuItem (localMenoryGroup, busLocalMemorySize == 16 << 20, "16MB", localMemoryListener),
  2051:         ComponentFactory.createRadioButtonMenuItem (localMenoryGroup, busLocalMemorySize == 32 << 20, "32MB", localMemoryListener),
  2052:         ComponentFactory.createRadioButtonMenuItem (localMenoryGroup, busLocalMemorySize == 64 << 20, "64MB", localMemoryListener),
  2053:         ComponentFactory.createRadioButtonMenuItem (localMenoryGroup, busLocalMemorySize == 128 << 20, "128MB", localMemoryListener),
  2054:         ComponentFactory.createRadioButtonMenuItem (localMenoryGroup, busLocalMemorySize == 256 << 20, "256MB", localMemoryListener),
  2055:         ComponentFactory.createRadioButtonMenuItem (localMenoryGroup, busLocalMemorySize == 384 << 20, "384MB", localMemoryListener),
  2056:         ComponentFactory.createRadioButtonMenuItem (localMenoryGroup, busLocalMemorySize == 512 << 20, "512MB", localMemoryListener),
  2057:         ComponentFactory.createRadioButtonMenuItem (localMenoryGroup, busLocalMemorySize == 768 << 20, "768MB", localMemoryListener),
  2058:         ComponentFactory.createHorizontalSeparator (),
  2059:         Multilingual.mlnText (
  2060:           ComponentFactory.createCheckBoxMenuItem (busLocalMemorySaveOn, "Save contents on exit", localMemoryListener),
  2061:           "ja", "終了時に内容を保存する"),
  2062:         ComponentFactory.createHorizontalSeparator (),
  2063:         Multilingual.mlnText (
  2064:           ComponentFactory.createCheckBoxMenuItem (busHimem68000, "Available on X68000", localMemoryListener),
  2065:           "ja", "X68000 でも有効"),
  2066:         Multilingual.mlnText (
  2067:           ComponentFactory.createCheckBoxMenuItem (busHighMemory060turboOn, "Available on X68030/Xellent30", localMemoryListener),
  2068:           "ja", "X68030/Xellent30 でも有効")
  2069:         ),
  2070:       "ja", "060turbo のハイメモリ");
  2071: 
  2072:     //Xellent30
  2073:     ActionListener xellent30Listener = new ActionListener () {
  2074:       @Override public void actionPerformed (ActionEvent ae) {
  2075:         Object source = ae.getSource ();
  2076:         String command = ae.getActionCommand ();
  2077:         switch (command) {
  2078:         case "$00EC0000-$00EC3FFF":
  2079:           xt3DIPSW = 0;
  2080:           break;
  2081:         case "$00EC4000-$00EC7FFF":
  2082:           xt3DIPSW = 1;
  2083:           break;
  2084:         case "$00EC8000-$00ECBFFF":
  2085:           xt3DIPSW = 2;
  2086:           break;
  2087:         case "$00ECC000-$00ECFFFF":
  2088:           xt3DIPSW = 3;
  2089:           break;
  2090:         case "256KB":
  2091:           xt3MemorySizeRequest = 1 << 18;
  2092:           break;
  2093:         case "1MB":
  2094:           xt3MemorySizeRequest = 1 << 20;
  2095:           break;
  2096:         case "Save contents on exit":  //終了時に内容を保存する
  2097:           xt3MemorySave = ((JCheckBoxMenuItem) source).isSelected ();
  2098:           break;
  2099:         }
  2100:       }
  2101:     };
  2102:     ButtonGroup xellent30PortGroup = new ButtonGroup ();
  2103:     ButtonGroup xellent30SizeGroup = new ButtonGroup ();
  2104:     JMenu xellent30Menu = ComponentFactory.createMenu (
  2105:       "Xellent30",
  2106:       ComponentFactory.createRadioButtonMenuItem (
  2107:         xellent30PortGroup,
  2108:         xt3DIPSW == 0,
  2109:         "$00EC0000-$00EC3FFF",
  2110:         xellent30Listener),
  2111:       ComponentFactory.createRadioButtonMenuItem (
  2112:         xellent30PortGroup,
  2113:         xt3DIPSW == 1,
  2114:         "$00EC4000-$00EC7FFF",
  2115:         xellent30Listener),
  2116:       ComponentFactory.createRadioButtonMenuItem (
  2117:         xellent30PortGroup,
  2118:         xt3DIPSW == 2,
  2119:         "$00EC8000-$00ECBFFF",
  2120:         xellent30Listener),
  2121:       ComponentFactory.createRadioButtonMenuItem (
  2122:         xellent30PortGroup,
  2123:         xt3DIPSW == 3,
  2124:         "$00ECC000-$00ECFFFF",
  2125:         xellent30Listener),
  2126:       ComponentFactory.createHorizontalSeparator (),
  2127:       ComponentFactory.createRadioButtonMenuItem (
  2128:         xellent30SizeGroup,
  2129:         xt3MemorySizeRequest == 1 << 18,
  2130:         "256KB",
  2131:         xellent30Listener),
  2132:       ComponentFactory.createRadioButtonMenuItem (
  2133:         xellent30SizeGroup,
  2134:         xt3MemorySizeRequest == 1 << 20,
  2135:         "1MB",
  2136:         xellent30Listener),
  2137:       ComponentFactory.createHorizontalSeparator (),
  2138:       Multilingual.mlnText (
  2139:         ComponentFactory.createCheckBoxMenuItem (xt3MemorySave, "Save contents on exit", xellent30Listener),
  2140:         "ja", "終了時に内容を保存する")
  2141:       );
  2142: 
  2143:     //アスペクト比
  2144:     ActionListener aspectListener = new ActionListener () {
  2145:       @Override public void actionPerformed (ActionEvent ae) {
  2146:         String command = ae.getActionCommand ();
  2147:         int i = command.indexOf (',');
  2148:         int key = Integer.parseInt (command.substring (0, i));
  2149:         int value = Integer.parseInt (command.substring (i + 1));
  2150:         pnlAspectMap[key] = value;
  2151:         pnlUpdateAspectTable ();
  2152:         pnlUpdateArrangement ();
  2153:       }  //actionPerformed
  2154:     };  //new ActionListener
  2155:     JMenu aspectMenu = ComponentFactory.createMenu ("Aspect ratio");
  2156:     for (int key = 0; key < PNL_ASPECT_KEYS; key++) {
  2157:       if (key != 0) {
  2158:         aspectMenu.add (ComponentFactory.createHorizontalSeparator ());
  2159:       }
  2160:       ButtonGroup group = new ButtonGroup ();
  2161:       for (int value = 0; value < PNL_ASPECT_VALUES; value++) {
  2162:         aspectMenu.add (
  2163:           ComponentFactory.setText (
  2164:             ComponentFactory.createRadioButtonMenuItem (
  2165:               group,  //buttonGroup
  2166:               pnlAspectMap[key] == value,  //selected
  2167:               key + "," + value,  //actionCommand
  2168:               aspectListener  //actionListener
  2169:               ),
  2170:             (PNL_ASPECT_MATRIX[key] == PNL_ASPECT_SCREEN_RATIO ?
  2171:              String.format ("%s %s (%.3f)",
  2172:                             PNL_ASPECT_RESOLUTION_NAME[key],
  2173:                             PNL_ASPECT_SCREEN_NAME[value],
  2174:                             PNL_ASPECT_SCREEN_RATIO[value]) :
  2175:              String.format ("%s %s (%.3f) @ %s (%.3f)",
  2176:                             PNL_ASPECT_RESOLUTION_NAME[key],
  2177:                             PNL_ASPECT_SCREEN_NAME[value],
  2178:                             PNL_ASPECT_SCREEN_RATIO[value],
  2179:                             PNL_ASPECT_PIXEL_NAME[value],
  2180:                             PNL_ASPECT_PIXEL_RATIO[value]))  //text
  2181:             )  //setText
  2182:           );  //add
  2183:       }  //for value
  2184:     }  //for key
  2185:     aspectMenu = Multilingual.mlnText (aspectMenu, "ja", "アスペクト比");
  2186: 
  2187:     //走査線エフェクト
  2188:     ActionListener scanlineListener = new ActionListener () {
  2189:       @Override public void actionPerformed (ActionEvent ae) {
  2190:         //Object source = ae.getSource ();
  2191:         String command = ae.getActionCommand ();
  2192:         switch (command) {
  2193:         case "Off":  //なし
  2194:           CRTC.crtScanlineEffect = CRTC.ScanlineEffect.OFF;
  2195:           CRTC.crtAllStamp += 2;
  2196:           break;
  2197:         case "Weak":  //弱
  2198:           CRTC.crtScanlineEffect = CRTC.ScanlineEffect.WEAK;
  2199:           CRTC.crtAllStamp += 2;
  2200:           break;
  2201:         case "Medium":  //中
  2202:           CRTC.crtScanlineEffect = CRTC.ScanlineEffect.MEDIUM;
  2203:           CRTC.crtAllStamp += 2;
  2204:           break;
  2205:         case "Strong":  //強
  2206:           CRTC.crtScanlineEffect = CRTC.ScanlineEffect.STRONG;
  2207:           CRTC.crtAllStamp += 2;
  2208:           break;
  2209:         case "Black":  //黒
  2210:           CRTC.crtScanlineEffect = CRTC.ScanlineEffect.BLACK;
  2211:           CRTC.crtAllStamp += 2;
  2212:           break;
  2213:         }
  2214:       }
  2215:     };
  2216:     ButtonGroup scanlineGroup = new ButtonGroup ();
  2217:     JMenu scanlineMenu =
  2218:       Multilingual.mlnText (
  2219:         ComponentFactory.createMenu (
  2220:           "Scanline effect",
  2221:           Multilingual.mlnText (
  2222:             ComponentFactory.createRadioButtonMenuItem (scanlineGroup, CRTC.crtScanlineEffect == CRTC.ScanlineEffect.OFF, "Off", scanlineListener),
  2223:             "ja", "なし"),
  2224:           Multilingual.mlnText (
  2225:             ComponentFactory.createRadioButtonMenuItem (scanlineGroup, CRTC.crtScanlineEffect == CRTC.ScanlineEffect.WEAK, "Weak", scanlineListener),
  2226:             "ja", "弱"),
  2227:           Multilingual.mlnText (
  2228:             ComponentFactory.createRadioButtonMenuItem (scanlineGroup, CRTC.crtScanlineEffect == CRTC.ScanlineEffect.MEDIUM, "Medium", scanlineListener),
  2229:             "ja", "中"),
  2230:           Multilingual.mlnText (
  2231:             ComponentFactory.createRadioButtonMenuItem (scanlineGroup, CRTC.crtScanlineEffect == CRTC.ScanlineEffect.STRONG, "Strong", scanlineListener),
  2232:             "ja", "強"),
  2233:           Multilingual.mlnText (
  2234:             ComponentFactory.createRadioButtonMenuItem (scanlineGroup, CRTC.crtScanlineEffect == CRTC.ScanlineEffect.BLACK, "Black", scanlineListener),
  2235:             "ja", "黒")
  2236:           ),
  2237:         "ja", "走査線エフェクト");
  2238: 
  2239:     ButtonGroup unitGroup = new ButtonGroup ();
  2240:     ButtonGroup frameGroup = new ButtonGroup ();
  2241:     ButtonGroup fullGroup = new ButtonGroup ();
  2242:     ButtonGroup hintGroup = new ButtonGroup ();
  2243:     ButtonGroup vgaGroup = new ButtonGroup ();
  2244:     ButtonGroup intermittentGroup = new ButtonGroup ();
  2245:     ButtonGroup sterescopicGroup = new ButtonGroup ();
  2246:     ButtonGroup soundInterpolationGroup = new ButtonGroup ();
  2247:     ButtonGroup adpcmInterpolationGroup = new ButtonGroup ();
  2248:     ButtonGroup adpcmOSCFreqGroup = new ButtonGroup ();
  2249:     ButtonGroup keyboardGroup = new ButtonGroup ();
  2250: 
  2251:     //改造
  2252:     DecimalSpinner[] freqSpinner = new DecimalSpinner[3];
  2253:     ChangeListener freqListener = new ChangeListener () {
  2254:       @Override public void stateChanged (ChangeEvent ce) {
  2255:         DecimalSpinner spinner = (DecimalSpinner) ce.getSource ();
  2256:         int i = spinner.getOption ();
  2257:         CRTC.crtFreqsRequest[i] = spinner.getIntValue ();
  2258:       }
  2259:     };
  2260:     for (int i = 0; i < 3; i++) {
  2261:       freqSpinner[i] = ComponentFactory.createDecimalSpinner (
  2262:         CRTC.crtFreqsRequest[i], CRTC.CRT_MIN_FREQ, CRTC.CRT_MAX_FREQ, 1000000, i, freqListener
  2263:         );
  2264:     }
  2265:     DecimalSpinner sprrasSpinner = ComponentFactory.createDecimalSpinner (
  2266:       SpriteScreen.sprSpritesPerRaster, 0, 256, 1, 0,
  2267:       new ChangeListener () {
  2268:         @Override public void stateChanged (ChangeEvent ce) {
  2269:           SpriteScreen.sprSpritesPerRaster = ((DecimalSpinner) ce.getSource ()).getIntValue ();
  2270:         }
  2271:       });
  2272:     ActionListener modificationListener = new ActionListener () {
  2273:       @Override public void actionPerformed (ActionEvent ae) {
  2274:         Object source = ae.getSource ();
  2275:         String command = ae.getActionCommand ();
  2276:         switch (command) {
  2277:         case "Extended graphic screen":  //拡張グラフィック画面
  2278:           CRTC.crtExtendedGraphicRequest = ((JCheckBoxMenuItem) source).isSelected ();
  2279:           break;
  2280:         case "1024-dot non-interlaced":  //1024 ドットノンインターレース
  2281:           CRTC.crtEleventhBitRequest = ((JCheckBoxMenuItem) source).isSelected ();
  2282:           break;
  2283:         case "Spherical scrolling of text screen":  //テキスト画面の球面スクロール
  2284:           CRTC.crtSetSphericalScrolling (((JCheckBoxMenuItem) source).isSelected ());
  2285:           break;
  2286:         case "* Reset to default values":  //* 初期値に戻す
  2287:           for (int i = 0; i < 3; i++) {
  2288:             if (CRTC.crtFreqsRequest[i] != CRTC.CRT_DEFAULT_FREQS[i]) {
  2289:               CRTC.crtFreqsRequest[i] = CRTC.CRT_DEFAULT_FREQS[i];
  2290:               freqSpinner[i].setIntValue (CRTC.crtFreqsRequest[i]);
  2291:             }
  2292:           }
  2293:           break;
  2294:         case "256 sprites":  //スプライト 256 枚
  2295:           SpriteScreen.sprDoubleSpritesRequest = ((JCheckBoxMenuItem) source).isSelected ();
  2296:           break;
  2297:         case "** Reset to default values":  //** 初期値に戻す
  2298:           if (SpriteScreen.sprSpritesPerRaster != 32) {
  2299:             SpriteScreen.sprSpritesPerRaster = 32;
  2300:             sprrasSpinner.setIntValue (SpriteScreen.sprSpritesPerRaster);
  2301:           }
  2302:           break;
  2303:         case "Can write 0 to bit 0 of CRTC R00":  //CRTC R00 のビット 0 に 0 を書き込める
  2304:           CRTC.crtR00Bit0Zero = ((JCheckBoxMenuItem) source).isSelected ();
  2305:           break;
  2306:         }
  2307:       }
  2308:     };
  2309:     JMenu modificationMenu =
  2310:       Multilingual.mlnText (
  2311:         ComponentFactory.createMenu (
  2312:           "Modification",
  2313:           !CRTC.CRT_EXTENDED_GRAPHIC ? null : Multilingual.mlnText (
  2314:             ComponentFactory.createCheckBoxMenuItem (CRTC.crtExtendedGraphicRequest, "Extended graphic screen", modificationListener),
  2315:             "ja", "拡張グラフィック画面"),
  2316:           Multilingual.mlnText (
  2317:             ComponentFactory.createCheckBoxMenuItem (CRTC.crtEleventhBitRequest, "1024-dot non-interlaced", modificationListener),
  2318:             "ja", "1024 ドットノンインターレース"),
  2319:           Multilingual.mlnText (
  2320:             ComponentFactory.createCheckBoxMenuItem (CRTC.crtSphericalScrolling, "Spherical scrolling of text screen", modificationListener),
  2321:             "ja", "テキスト画面の球面スクロール"),
  2322:           ComponentFactory.createHorizontalSeparator (),
  2323:           ComponentFactory.createHorizontalBox (
  2324:             Box.createHorizontalStrut (20),
  2325:             Multilingual.mlnText (ComponentFactory.createLabel ("Dot clock oscillattor"), "ja", "ドットクロックオシレータ"),
  2326:             Box.createHorizontalGlue ()
  2327:             ),
  2328:           ComponentFactory.createHorizontalBox (
  2329:             Box.createHorizontalStrut (20),
  2330:             freqSpinner[0],
  2331:             ComponentFactory.createLabel (" Hz *"),
  2332:             Box.createHorizontalGlue ()
  2333:             ),
  2334:           ComponentFactory.createHorizontalBox (
  2335:             Box.createHorizontalStrut (20),
  2336:             freqSpinner[1],
  2337:             ComponentFactory.createLabel (" Hz *"),
  2338:             Box.createHorizontalGlue ()
  2339:             ),
  2340:           ComponentFactory.createHorizontalBox (
  2341:             Box.createHorizontalStrut (20),
  2342:             freqSpinner[2],
  2343:             ComponentFactory.createLabel (" Hz *"),
  2344:             Box.createHorizontalGlue ()
  2345:             ),
  2346:           Multilingual.mlnText (
  2347:             ComponentFactory.createMenuItem ("* Reset to default values", modificationListener),
  2348:             "ja", "* 初期値に戻す"),
  2349:           ComponentFactory.createHorizontalSeparator (),
  2350:           Multilingual.mlnText (
  2351:             ComponentFactory.createCheckBoxMenuItem (SpriteScreen.sprDoubleSpritesRequest, "256 sprites", modificationListener),
  2352:             "ja", "スプライト 256 枚"),
  2353:           ComponentFactory.createHorizontalSeparator (),
  2354:           ComponentFactory.createHorizontalBox (
  2355:             Box.createHorizontalStrut (20),
  2356:             Multilingual.mlnText (ComponentFactory.createLabel ("Number of sprites per raster"), "ja", "ラスタあたりのスプライトの枚数"),
  2357:             Box.createHorizontalGlue ()
  2358:             ),
  2359:           ComponentFactory.createHorizontalBox (
  2360:             Box.createHorizontalStrut (20),
  2361:             sprrasSpinner,
  2362:             ComponentFactory.createLabel (" **"),
  2363:             Box.createHorizontalGlue ()
  2364:             ),
  2365:           Multilingual.mlnText (
  2366:             ComponentFactory.createMenuItem ("** Reset to default values", modificationListener),
  2367:             "ja", "** 初期値に戻す"),
  2368:           ComponentFactory.createHorizontalSeparator (),
  2369:           Multilingual.mlnText (
  2370:             ComponentFactory.createCheckBoxMenuItem (CRTC.crtR00Bit0Zero, "Can write 0 to bit 0 of CRTC R00", modificationListener),
  2371:             "ja", "CRTC R00 のビット 0 に 0 を書き込める")
  2372:           ),
  2373:         "ja", "改造");
  2374: 
  2375:     //メニューバー
  2376:     mnbMenuBar = ComponentFactory.createMenuBar (
  2377: 
  2378:       //ファイルメニュー
  2379:       mnbFileMenu = Multilingual.mlnText (
  2380:         ComponentFactory.createMenu (
  2381:           "File", 'F',
  2382:           //FDDメニュー
  2383:           FDC.fdcMenu,
  2384:           //SASI HDDメニュー
  2385:           HDC.hdcMenu,
  2386:           //内蔵 SCSI HDDメニュー
  2387:           SPC.spcMenu,
  2388:           //HFSメニュー
  2389:           HFS.hfsMenu,
  2390:           ComponentFactory.createHorizontalSeparator (),
  2391:           mnbQuitMenuItem = Multilingual.mlnText (ComponentFactory.createMenuItem ("Quit", 'Q', MNB_MODIFIERS, listener), "ja", "終了")
  2392:           ),
  2393:         "ja", "ファイル"),
  2394: 
  2395:       //MPUメニュー
  2396:       mpuMenu,
  2397: 
  2398:       //画面メニュー
  2399:       mnbDisplayMenu = Multilingual.mlnText (
  2400:         ComponentFactory.createMenu (
  2401:           "Display", 'D',
  2402:           mnbFullscreenMenuItem = ComponentFactory.setEnabled (
  2403:             Multilingual.mlnText (
  2404:               ComponentFactory.createRadioButtonMenuItem (
  2405:                 fullGroup, pnlFullscreenOn,
  2406:                 "Full screen", KeyEvent.VK_F11, listener), "ja", "全画面表示"),
  2407:             pnlIsFullscreenSupported),  //全画面表示に移行できるとき
  2408:           mnbFitInWindowMenuItem = ComponentFactory.setEnabled (
  2409:             Multilingual.mlnText (
  2410:               ComponentFactory.createRadioButtonMenuItem (
  2411:                 fullGroup, !pnlFullscreenOn && pnlFitInWindowOn,
  2412:                 "Fit in window", 'W', MNB_MODIFIERS, listener), "ja", "ウインドウに合わせる"),
  2413:             pnlIsFitInWindowSupported),  //ウインドウに合わせられるとき
  2414:           mnbFixedScaleMenuItem = Multilingual.mlnText (
  2415:             ComponentFactory.createRadioButtonMenuItem (
  2416:               fullGroup, !pnlFullscreenOn && !pnlFitInWindowOn,
  2417:               "Fixed scale", 'X', MNB_MODIFIERS, listener), "ja", "固定倍率"),
  2418:           ComponentFactory.createHorizontalBox (
  2419:             Box.createHorizontalStrut (20),
  2420:             pnlFixedSpinner,
  2421:             ComponentFactory.createLabel ("%"),
  2422:             Box.createHorizontalGlue ()
  2423:             ),
  2424:           ComponentFactory.createMenuItem ("50%", listener),
  2425:           ComponentFactory.createMenuItem ("75%", listener),
  2426:           ComponentFactory.createMenuItem ("100%", listener),
  2427:           ComponentFactory.createMenuItem ("150%", listener),
  2428:           ComponentFactory.createMenuItem ("200%", listener),
  2429:           //アスペクト比
  2430:           aspectMenu,
  2431:           //補間アルゴリズム
  2432:           Multilingual.mlnText (
  2433:             ComponentFactory.createMenu (
  2434:               "Interpolation algorithm",
  2435:               Multilingual.mlnText (
  2436:                 ComponentFactory.createRadioButtonMenuItem (
  2437:                   hintGroup, pnlInterpolation == RenderingHints.VALUE_INTERPOLATION_NEAREST_NEIGHBOR,
  2438:                   "Nearest neighbor", listener),
  2439:                 "ja", "最近傍補間"),
  2440:               Multilingual.mlnText (
  2441:                 ComponentFactory.createRadioButtonMenuItem (
  2442:                   hintGroup, pnlInterpolation == RenderingHints.VALUE_INTERPOLATION_BILINEAR,
  2443:                   "Bilinear", listener),
  2444:                 "ja", "線形補間"),
  2445:               Multilingual.mlnText (
  2446:                 ComponentFactory.createRadioButtonMenuItem (
  2447:                   hintGroup, pnlInterpolation == RenderingHints.VALUE_INTERPOLATION_BICUBIC,
  2448:                   "Bicubic", listener),
  2449:                 "ja", "三次補間")
  2450:               ),
  2451:             "ja", "補間アルゴリズム"),
  2452:           //走査線エフェクト
  2453:           scanlineMenu,
  2454:           //間欠描画
  2455:           !CRTC.CRT_ENABLE_INTERMITTENT ? null : Multilingual.mlnText (
  2456:             ComponentFactory.createMenu (
  2457:               "Intermittent drawing",
  2458:               Multilingual.mlnText (
  2459:                 ComponentFactory.createRadioButtonMenuItem (
  2460:                   intermittentGroup, CRTC.crtIntermittentInterval == 0, "Draw all changed pictures", listener),
  2461:                 "ja", "変化した画像をすべて描画する"),
  2462:               Multilingual.mlnText (
  2463:                 ComponentFactory.createRadioButtonMenuItem (
  2464:                   intermittentGroup, CRTC.crtIntermittentInterval == 1, "Draw a changed picture once every two times", listener),
  2465:                 "ja", "変化した画像を 2 回に 1 回描画する"),
  2466:               Multilingual.mlnText (
  2467:                 ComponentFactory.createRadioButtonMenuItem (
  2468:                   intermittentGroup, CRTC.crtIntermittentInterval == 2, "Draw a changed picture once every three times", listener),
  2469:                 "ja", "変化した画像を 3 回に 1 回描画する"),
  2470:               Multilingual.mlnText (
  2471:                 ComponentFactory.createRadioButtonMenuItem (
  2472:                   intermittentGroup, CRTC.crtIntermittentInterval == 3, "Draw a changed picture once every four times", listener),
  2473:                 "ja", "変化した画像を 4 回に 1 回描画する"),
  2474:               Multilingual.mlnText (
  2475:                 ComponentFactory.createRadioButtonMenuItem (
  2476:                   intermittentGroup, CRTC.crtIntermittentInterval == 4, "Draw a changed picture once every five times", listener),
  2477:                 "ja", "変化した画像を 5 回に 1 回描画する")
  2478:               ),
  2479:             "ja", "間欠描画"),
  2480:           //立体視
  2481:           !PNL_STEREOSCOPIC_ON ? null : ComponentFactory.createHorizontalSeparator (),
  2482:           mnbStereoscopicMenuItem = !PNL_STEREOSCOPIC_ON ? null : Multilingual.mlnText (
  2483:             ComponentFactory.createCheckBoxMenuItem (pnlStereoscopicOn, "Stereoscopic viewing", 'T', listener),
  2484:             "ja", "立体視"),
  2485:           !PNL_STEREOSCOPIC_ON ? null : Multilingual.mlnText (
  2486:             ComponentFactory.createMenu (
  2487:               "Stereoscopic settings",
  2488:               !PNL_STEREOSCOPIC_ON ? null : Multilingual.mlnText (
  2489:                 ComponentFactory.createRadioButtonMenuItem (sterescopicGroup,
  2490:                                                             pnlStereoscopicMethod == PNL_NAKED_EYE_CROSSING,
  2491:                                                             "Naked-eye crossing", listener),
  2492:                 "ja", "裸眼交差法"),
  2493:               !PNL_STEREOSCOPIC_ON ? null : Multilingual.mlnText (
  2494:                 ComponentFactory.createRadioButtonMenuItem (sterescopicGroup,
  2495:                                                             pnlStereoscopicMethod == PNL_NAKED_EYE_PARALLEL,
  2496:                                                             "Naked-eye parallel", listener),
  2497:                 "ja", "裸眼平行法"),
  2498:               !PNL_STEREOSCOPIC_ON ? null : Multilingual.mlnText (
  2499:                 ComponentFactory.createRadioButtonMenuItem (sterescopicGroup,
  2500:                                                             pnlStereoscopicMethod == PNL_SIDE_BY_SIDE,
  2501:                                                             "Side-by-side", listener),
  2502:                 "ja", "サイドバイサイド"),
  2503:               !PNL_STEREOSCOPIC_ON ? null : Multilingual.mlnText (
  2504:                 ComponentFactory.createRadioButtonMenuItem (sterescopicGroup,
  2505:                                                             pnlStereoscopicMethod == PNL_TOP_AND_BOTTOM,
  2506:                                                             "Top-and-bottom", listener),
  2507:                 "ja", "トップアンドボトム")
  2508:               ),
  2509:             "ja", "立体視設定"),
  2510:           //GIFアニメーション
  2511:           ComponentFactory.createHorizontalSeparator (),
  2512:           GIFAnimation.gifStartRecordingMenuItem,
  2513:           GIFAnimation.gifSettingsMenu,
  2514:           //改造
  2515:           ComponentFactory.createHorizontalSeparator (),
  2516:           modificationMenu,
  2517:           //
  2518:           SpritePatternViewer.SPV_ON ? Multilingual.mlnText (ComponentFactory.createMenuItem ("Sprite pattern viewer", listener), "ja", "スプライトパターンビュア") : null,
  2519:           ScreenModeTest.SMT_ON ? Multilingual.mlnText (ComponentFactory.createMenuItem ("Screen mode test", listener), "ja", "表示モードテスト") : null
  2520:           ),
  2521:         "ja", "画面"),
  2522: 
  2523:       //音声メニュー
  2524:       mnbSoundMenu = ComponentFactory.setEnabled (
  2525:         Multilingual.mlnText (
  2526:           ComponentFactory.createMenu (
  2527:             "Sound", 'S',
  2528:             mnbPlayMenuItem = ComponentFactory.setEnabled (
  2529:               Multilingual.mlnText (ComponentFactory.createCheckBoxMenuItem (SoundSource.sndPlayOn, "Play", 'P', MNB_MODIFIERS, listener), "ja", "音声出力"),
  2530:               SoundSource.sndLine != null),
  2531:             //ボリュームのラベル
  2532:             //  JLabelのalignmentでセンタリングしようとするとチェックボックスのサイズの分だけ右に寄ってしまう
  2533:             //  Boxで囲み、左右にglueを置くことでセンタリングする
  2534:             ComponentFactory.createHorizontalBox (
  2535:               Box.createHorizontalGlue (),
  2536:               Multilingual.mlnText (ComponentFactory.createLabel ("Volume "), "ja", "音量 "),
  2537:               mnbVolumeLabel = ComponentFactory.createLabel (String.valueOf (SoundSource.sndVolume)),
  2538:               Box.createHorizontalGlue ()
  2539:               ),
  2540:             //ボリュームスライダ
  2541:             //  デフォルトのサイズだと間延びした感じになるので幅を狭くする
  2542:             ComponentFactory.setPreferredSize (
  2543:               ComponentFactory.createHorizontalSlider (
  2544:                 0,
  2545:                 SoundSource.SND_VOLUME_MAX,
  2546:                 SoundSource.sndVolume,
  2547:                 SoundSource.SND_VOLUME_STEP,
  2548:                 1,
  2549:                 new ChangeListener () {
  2550:                   @Override public void stateChanged (ChangeEvent ce) {
  2551:                     SoundSource.sndSetVolume (((JSlider) ce.getSource ()).getValue ());
  2552:                   }
  2553:                 }),
  2554:               LnF.lnfFontSize * 18, LnF.lnfFontSize * 2 + 28),
  2555:             Multilingual.mlnText (
  2556:               ComponentFactory.createMenu (
  2557:                 "Sound interpolation",
  2558:                 Multilingual.mlnText (
  2559:                   ComponentFactory.createRadioButtonMenuItem (
  2560:                     soundInterpolationGroup, SoundSource.sndRateConverter == SoundSource.SNDRateConverter.THINNING_STEREO,
  2561:                     "Sound thinning", listener),
  2562:                   "ja", "音声 間引き"),
  2563:                 Multilingual.mlnText (
  2564:                   ComponentFactory.createRadioButtonMenuItem (
  2565:                     soundInterpolationGroup, SoundSource.sndRateConverter == SoundSource.SNDRateConverter.LINEAR_STEREO,
  2566:                     "Sound linear interpolation", listener),
  2567:                   "ja", "音声 線形補間"),
  2568:                 ComponentFactory.setEnabled (
  2569:                   Multilingual.mlnText (
  2570:                     ComponentFactory.createRadioButtonMenuItem (
  2571:                       soundInterpolationGroup, SoundSource.sndRateConverter == SoundSource.SNDRateConverter.CONSTANT_AREA_STEREO_48000,
  2572:                       "Sound piecewise-constant area interpolation", listener),
  2573:                     "ja", "音声 区分定数面積補間"),
  2574:                   SoundSource.SND_CHANNELS == 2 && SoundSource.SND_SAMPLE_FREQ == 48000),
  2575:                 ComponentFactory.setEnabled (
  2576:                   Multilingual.mlnText (
  2577:                     ComponentFactory.createRadioButtonMenuItem (
  2578:                       soundInterpolationGroup, SoundSource.sndRateConverter == SoundSource.SNDRateConverter.LINEAR_AREA_STEREO_48000,
  2579:                       "Sound linear area interpolation", listener),
  2580:                     "ja", "音声 線形面積補間"),
  2581:                   SoundSource.SND_CHANNELS == 2 && SoundSource.SND_SAMPLE_FREQ == 48000)
  2582:                 ),
  2583:               "ja", "音声補間"),
  2584:             Multilingual.mlnText (ComponentFactory.createMenuItem ("Sound monitor", listener), "ja", "音声モニタ"),
  2585:             //
  2586:             ComponentFactory.createHorizontalSeparator (),
  2587:             //
  2588:             ComponentFactory.setEnabled (
  2589:               Multilingual.mlnText (ComponentFactory.createCheckBoxMenuItem (OPM.opmOutputMask != 0, "OPM output", listener), "ja", "OPM 出力"),
  2590:               SoundSource.sndLine != null),
  2591:             !OPMLog.OLG_ON ? null : Multilingual.mlnText (ComponentFactory.createMenuItem ("OPM log", listener), "ja", "OPM ログ"),
  2592:             //
  2593:             ComponentFactory.createHorizontalSeparator (),
  2594:             //
  2595:             ComponentFactory.setEnabled (
  2596:               Multilingual.mlnText (ComponentFactory.createCheckBoxMenuItem (ADPCM.pcmOutputOn, "PCM output", listener), "ja", "PCM 出力"),
  2597:               SoundSource.sndLine != null),
  2598:             Multilingual.mlnText (
  2599:               ComponentFactory.createMenu (
  2600:                 "PCM interpolation",
  2601:                 Multilingual.mlnText (
  2602:                   ComponentFactory.createRadioButtonMenuItem (
  2603:                     adpcmInterpolationGroup, ADPCM.pcmInterpolationAlgorithm == ADPCM.PCM_INTERPOLATION_CONSTANT,
  2604:                     "PCM piecewise-constant interpolation", listener),
  2605:                   "ja", "PCM 区分定数補間"),
  2606:                 Multilingual.mlnText (
  2607:                   ComponentFactory.createRadioButtonMenuItem (
  2608:                     adpcmInterpolationGroup, ADPCM.pcmInterpolationAlgorithm == ADPCM.PCM_INTERPOLATION_LINEAR,
  2609:                     "PCM linear interpolation", listener),
  2610:                   "ja", "PCM 線形補間"),
  2611:                 Multilingual.mlnText (
  2612:                   ComponentFactory.createRadioButtonMenuItem (
  2613:                     adpcmInterpolationGroup, ADPCM.pcmInterpolationAlgorithm == ADPCM.PCM_INTERPOLATION_HERMITE,
  2614:                     "PCM hermite interpolation", listener),
  2615:                   "ja", "PCM エルミート補間")
  2616:                 ),
  2617:               "ja", "PCM 補間"),
  2618:             Multilingual.mlnText (
  2619:               ComponentFactory.createMenu (
  2620:                 "PCM source oscillator frequency",
  2621:                 ComponentFactory.createRadioButtonMenuItem (adpcmOSCFreqGroup, ADPCM.pcmOSCFreqRequest == 0, "PCM 8MHz/4MHz", listener),
  2622:                 ComponentFactory.createRadioButtonMenuItem (adpcmOSCFreqGroup, ADPCM.pcmOSCFreqRequest == 1, "PCM 8MHz/16MHz", listener)
  2623:                 ),
  2624:               "ja", "PCM 原発振周波数")
  2625:             ),
  2626:           "ja", "音声"),
  2627:         SoundSource.sndLine != null),
  2628: 
  2629:       //入力メニュー
  2630:       mnbInputMenu = Multilingual.mlnText (
  2631:         ComponentFactory.createMenu (
  2632:           "Input", 'I',
  2633:           mnbPasteMenuItem = Multilingual.mlnText (ComponentFactory.createMenuItem ("Paste", 'V', MNB_MODIFIERS, listener), "ja", "貼り付け"),
  2634:           CONDevice.conSettingsMenu,
  2635:           ComponentFactory.createHorizontalSeparator (),
  2636:           mnbNoKeyboardMenuItem = Multilingual.mlnText (
  2637:             ComponentFactory.createRadioButtonMenuItem (keyboardGroup, !Keyboard.kbdOn, "No keyboard", 'K', MNB_MODIFIERS, listener),
  2638:             "ja", "キーボードなし"),
  2639:           mnbStandardKeyboardMenuItem = Multilingual.mlnText (
  2640:             ComponentFactory.createRadioButtonMenuItem (keyboardGroup, Keyboard.kbdOn && Keyboard.kbdType == Keyboard.KBD_STANDARD_TYPE, "Standard keyboard", listener),
  2641:             "ja", "標準キーボード"),
  2642:           mnbCompactKeyboardMenuItem = Multilingual.mlnText (
  2643:             ComponentFactory.createRadioButtonMenuItem (keyboardGroup, Keyboard.kbdOn && Keyboard.kbdType == Keyboard.KBD_COMPACT_TYPE, "Compact keyboard", listener),
  2644:             "ja", "コンパクトキーボード"),
  2645:           Multilingual.mlnText (ComponentFactory.createMenuItem ("Key assignments", listener), "ja", "キー割り当て"),
  2646:           Keyboard.kbdF11KeyMenu,
  2647:           SRAM.smrRepeatDelayMenu,
  2648:           SRAM.smrRepeatIntervalMenu,
  2649:           !Keyboard.KBD_ZKEY_ON ? null : Keyboard.kbdZKeyMenu,
  2650:           ComponentFactory.createHorizontalSeparator (),
  2651:           Mouse.musSeamlessMouseCheckBox,
  2652:           Mouse.musWheelMenu,
  2653:           Mouse.musCtrlRightCheckBox,
  2654:           Mouse.musEdgeAccelerationCheckBox,
  2655:           Mouse.musMouseCursorSpeedBox,
  2656:           Mouse.musSpeedSlider,
  2657:           Mouse.musHostsPixelUnitsCheckBox,
  2658:           ComponentFactory.createHorizontalSeparator (),
  2659:           Multilingual.mlnText (ComponentFactory.createMenuItem ("Joystick port settings", listener), "ja", "ジョイスティックポート設定")
  2660:           ),
  2661:         "ja", "入力"),
  2662: 
  2663:       //設定メニュー
  2664:       mnbConfigMenu = Multilingual.mlnText (
  2665:         ComponentFactory.createMenu (
  2666:           "Config", 'C',
  2667:           Multilingual.mlnText (ComponentFactory.createMenuItem ("RS-232C and terminal", listener), "ja", "RS-232C とターミナル"),
  2668:           Multilingual.mlnText (
  2669:             ComponentFactory.createMenu (
  2670:               "Debug",
  2671:               Multilingual.mlnText (ComponentFactory.createMenuItem ("Console", listener), "ja", "コンソール"),
  2672:               Multilingual.mlnText (ComponentFactory.createMenuItem ("Register list", listener), "ja", "レジスタリスト"),
  2673:               Multilingual.mlnText (ComponentFactory.createMenuItem ("Disassemble list", listener), "ja", "逆アセンブルリスト"),
  2674:               Multilingual.mlnText (ComponentFactory.createMenuItem ("Memory dump list", listener), "ja", "メモリダンプリスト"),
  2675:               Multilingual.mlnText (ComponentFactory.createMenuItem ("Logical space monitor", listener), "ja", "論理空間モニタ"),
  2676:               Multilingual.mlnText (ComponentFactory.createMenuItem ("Physical space monitor", listener), "ja", "物理空間モニタ"),
  2677:               ATCMonitor.ACM_ON ? Multilingual.mlnText (ComponentFactory.createMenuItem ("Address translation caches monitor", listener), "ja", "アドレス変換キャッシュモニタ") : null,
  2678:               BranchLog.BLG_ON ? Multilingual.mlnText (ComponentFactory.createMenuItem ("Branch log", listener), "ja", "分岐ログ") : null,
  2679:               ProgramFlowVisualizer.PFV_ON ? Multilingual.mlnText (ComponentFactory.createMenuItem ("Program flow visualizer", listener), "ja", "プログラムフロービジュアライザ") : null,
  2680:               RasterBreakPoint.RBP_ON ? Multilingual.mlnText (ComponentFactory.createMenuItem ("Raster break point", listener), "ja", "ラスタブレークポイント") : null,
  2681:               DataBreakPoint.DBP_ON ? Multilingual.mlnText (ComponentFactory.createMenuItem ("Data break point", listener), "ja", "データブレークポイント") : null,
  2682:               RootPointerList.RTL_ON ? Multilingual.mlnText (ComponentFactory.createMenuItem ("Root pointer list", listener), "ja", "ルートポインタリスト") : null,
  2683:               ComponentFactory.createHorizontalSeparator (),
  2684:               SRAM.smrROMDBMenuItem
  2685:               ),
  2686:             "ja", "デバッグ"),
  2687:           SRAM.smrBootMenu,
  2688:           mainMemoryMenu,
  2689:           highMemoryMenu,
  2690:           localMemoryMenu,
  2691:           xellent30Menu,
  2692:           ComponentFactory.createHorizontalSeparator (),
  2693:           ComponentFactory.createMenu (
  2694:             "RTC",
  2695:             Multilingual.mlnText (
  2696:               ComponentFactory.createMenuItem ("Adjust clock to host", listener),
  2697:               "ja", "時計をホストに合わせる")
  2698:             ),
  2699:           SRAM.smrMenu,
  2700:           Settings.sgsMenu,
  2701:           ComponentFactory.createHorizontalSeparator (),
  2702:           Multilingual.mlnText (ComponentFactory.createMenuItem ("Printer", listener), "ja", "プリンタ"),
  2703:           ROM.romMenu,
  2704:           Multilingual.mlnText (
  2705:             ComponentFactory.createMenu (
  2706:               "Miscellaneous",
  2707:               SlowdownTest.sdtCheckBoxMenuItem,
  2708:               SlowdownTest.sdtBox,
  2709:               Multilingual.mlnText (
  2710:                 ComponentFactory.createCheckBoxMenuItem (Mouse.musOutputButtonStatus, "Mouse button status", listener),
  2711:                 "ja", "マウスのボタンの状態"),
  2712:               Z8530.SCC_DEBUG_ON ? Z8530.sccDebugMenu : null
  2713:               ),
  2714:             "ja", "その他"),
  2715:           ComponentFactory.createHorizontalSeparator (),
  2716:           Multilingual.mlnText (
  2717:             ComponentFactory.createMenuItem ("Java runtime environment information", listener),
  2718:             "ja", "Java 実行環境の情報"),
  2719:           Multilingual.mlnText (
  2720:             ComponentFactory.createMenuItem ("Version information", listener),
  2721:             "ja", "バージョン情報"),
  2722:           Multilingual.mlnText (
  2723:             ComponentFactory.createMenu (
  2724:               "License",
  2725:               Multilingual.mlnText (ComponentFactory.createMenuItem ("XEiJ License", listener), "ja", "XEiJ 使用許諾条件"),
  2726:               Multilingual.mlnText (ComponentFactory.createMenuItem ("FSHARP License", listener), "ja", "FSHARP 許諾条件"),
  2727:               Multilingual.mlnText (ComponentFactory.createMenuItem ("ymfm License", listener), "ja", "ymfm License"),
  2728:               Multilingual.mlnText (ComponentFactory.createMenuItem ("jSerialComm License", listener), "ja", "jSerialComm License")
  2729:               ),
  2730:             "ja", "使用許諾条件")
  2731:           ),
  2732:         "ja", "設定"),
  2733: 
  2734:       mnbMakeLanguageMenu (),  //言語メニュー
  2735: 
  2736:       //インジケータ
  2737:       Box.createHorizontalGlue (),  //インジケータをセンタリングする
  2738:       ComponentFactory.createVerticalBox (
  2739:         Box.createVerticalGlue (),
  2740:         Indicator.indBox,
  2741:         Box.createVerticalGlue ()
  2742:         ),
  2743:       Box.createHorizontalGlue ()
  2744: 
  2745:       );
  2746:   }  //mnbMakeMenu()
  2747: 
  2748: 
  2749: 
  2750:   //========================================================================================
  2751:   //$$FRM フレーム
  2752: 
  2753:   //モード
  2754:   public static boolean frmIsActive;  //true=フォーカスがある
  2755: 
  2756:   //フレーム
  2757:   public static JFrame frmFrame;  //フレーム
  2758:   public static int frmMarginWidth;  //パネルからフレームまでのマージン
  2759:   public static int frmMarginHeight;
  2760:   public static Dimension frmMinimumSize;  //pnlMinimumWidth+frmMarginWidth,pnlMinimumHeight+frmMarginHeight フレームの最小サイズ
  2761: 
  2762:   //スクリーンデバイス
  2763:   public static GraphicsDevice frmScreenDevice;  //スクリーンデバイス
  2764: 
  2765:   //ドラッグアンドドロップ
  2766:   public static DropTarget frmDropTarget;
  2767: 
  2768:   //frmInit ()
  2769:   //  フレームを初期化する
  2770:   public static void frmInit () {
  2771:     frmIsActive = false;
  2772:     frmScreenDevice = GraphicsEnvironment.getLocalGraphicsEnvironment ().getDefaultScreenDevice ();  //スクリーンデバイス
  2773:     pnlIsFullscreenSupported = frmScreenDevice.isFullScreenSupported ();  //全画面表示に移行できるかどうか
  2774:     pnlIsFitInWindowSupported = true;  //ウインドウに合わせられるかどうか
  2775:   }  //frmInit()
  2776: 
  2777:   //frmMake ()
  2778:   //  フレームを作る
  2779:   public static void frmMake () {
  2780: 
  2781:     //フレーム
  2782:     frmFrame = ComponentFactory.createRestorableFrame (
  2783:       Settings.SGS_FRM_FRAME_KEY,
  2784:       PRG_TITLE + " version " + PRG_VERSION,
  2785:       mnbMenuBar,
  2786:       pnlPanel);
  2787:     frmUpdateTitle ();
  2788:     frmFrame.setIconImage (LnF.LNF_ICON_IMAGE_48);  //タスクバーのアイコンを変更する
  2789:     frmFrame.setDefaultCloseOperation (WindowConstants.DISPOSE_ON_CLOSE);
  2790:     //frmFrame.setResizable (false);  //リサイズ不可
  2791: 
  2792:     //パネルからフレームまでのマージンを確認する
  2793:     frmMarginWidth = frmFrame.getWidth () - pnlWidth;
  2794:     frmMarginHeight = frmFrame.getHeight () - pnlHeight;
  2795:     frmMinimumSize = new Dimension (pnlMinimumWidth + frmMarginWidth, pnlMinimumHeight + frmMarginHeight);
  2796:     frmFrame.setMinimumSize (frmMinimumSize);
  2797: 
  2798:     //ドラッグアンドドロップ
  2799:     //  FDイメージが放り込まれたらそこから再起動する
  2800:     frmDropTarget = new DropTarget (pnlPanel, DnDConstants.ACTION_COPY, new DropTargetAdapter () {
  2801:       @Override public void dragOver (DropTargetDragEvent dtde) {
  2802:         if (dtde.isDataFlavorSupported (DataFlavor.javaFileListFlavor)) {
  2803:           dtde.acceptDrag (DnDConstants.ACTION_COPY);
  2804:           return;
  2805:         }
  2806:         dtde.rejectDrag ();
  2807:       }
  2808:       @Override public void drop (DropTargetDropEvent dtde) {
  2809:         try {
  2810:           if (dtde.isDataFlavorSupported (DataFlavor.javaFileListFlavor)) {
  2811:             dtde.acceptDrop (DnDConstants.ACTION_COPY);
  2812:             boolean reset = false;  //true=ここから再起動,false=開く
  2813:             int fdu0 = -1;
  2814:             int fdu = 0;
  2815:             int hdu0 = -1;
  2816:             int hdu = 0;
  2817:             int scu0 = -1;
  2818:             int scu = 0;
  2819:             int hfu0 = -1;
  2820:             int hfu = 0;
  2821:             for (Object o : (java.util.List) dtde.getTransferable ().getTransferData (DataFlavor.javaFileListFlavor)) {
  2822:               if (o instanceof File) {
  2823:                 File file = (File) o;
  2824:                 if (file.isFile ()) {  //ファイルのとき。HFS以外のフィルタがディレクトリを受け入れてしまうのでディレクトリを除外する
  2825:                   if (FDC.fdcFileFilter.accept (file)) {  //FDのイメージファイルのとき
  2826:                     if (fdu < FDC.FDC_MAX_UNITS &&
  2827:                         FDC.fdcUnitArray[fdu].insert (file.getPath (), false)) {  //挿入できた
  2828:                       if (fdu0 < 0) {
  2829:                         fdu0 = fdu;
  2830:                       }
  2831:                       fdu++;
  2832:                       continue;
  2833:                     }
  2834:                   }
  2835:                   if (HDC.hdcFileFilter.accept (file)) {  //SASIハードディスクのイメージファイルのとき
  2836:                     if (hdu < 16 &&
  2837:                         HDC.hdcUnitArray[hdu].insert (file.getPath (), false)) {  //挿入できた
  2838:                       if (hdu0 < 0) {
  2839:                         hdu0 = hdu;
  2840:                       }
  2841:                       hdu++;
  2842:                       continue;
  2843:                     }
  2844:                   }
  2845:                   if (SPC.spcFileFilter.accept (file)) {  //SCSIハードディスク/CD-ROMのイメージファイルのとき
  2846:                     if (scu < 16 &&
  2847:                         SPC.spcUnitArray[scu].insert (file.getPath (), false)) {  //挿入できた
  2848:                       if (scu0 < 0) {
  2849:                         scu0 = scu;
  2850:                       }
  2851:                       scu++;
  2852:                       continue;
  2853:                     }
  2854:                   }
  2855:                 }
  2856:                 if (HFS.hfsFileFilter.accept (file)) {  //ディレクトリまたはHUMAN.SYSのとき
  2857:                   if (hfu < HFS.HFS_MAX_UNITS &&
  2858:                       HFS.hfsUnitArray[hfu].insert (file.getPath (), false)) {  //挿入できた
  2859:                     if (hfu0 < 0) {
  2860:                       hfu0 = hfu;
  2861:                     }
  2862:                     hfu++;
  2863:                     continue;
  2864:                   }
  2865:                 }
  2866:               }
  2867:               reset = false;  //挿入できないファイルがあったときはリセットをキャンセルする
  2868:             }
  2869:             dtde.dropComplete (true);
  2870:             if (reset) {
  2871:               if (fdu0 >= 0) {
  2872:                 mpuReset (0x9070 | fdu0 << 8, -1);
  2873:               } else if (hdu0 >= 0) {
  2874:                 mpuReset (0x8000 | hdu0 << 8, -1);
  2875:               } else if (scu0 >= 0) {
  2876:                 mpuReset (0xa000, SPC.SPC_HANDLE_EX + (scu0 << 2));  //拡張SCSIがなければ内蔵SCSIに読み替えられる
  2877:               } else if (hfu0 >= 0) {
  2878:                 HFS.hfsBootUnit = hfu0;
  2879:                 mpuReset (0xa000, HFS.HFS_BOOT_HANDLE);
  2880:               }
  2881:             }
  2882:             return;
  2883:           }
  2884:         } catch (UnsupportedFlavorException ufe) {
  2885:           //ufe.printStackTrace ();
  2886:         } catch (IOException ioe) {
  2887:           //ioe.printStackTrace ();
  2888:         }
  2889:         dtde.rejectDrop();
  2890:       }
  2891:     });
  2892: 
  2893:   }  //frmMake()
  2894: 
  2895:   //frmUpdateTitle ()
  2896:   //  フレームのタイトルを更新する
  2897:   public static void frmUpdateTitle () {
  2898:     frmFrame.setTitle ((currentAccelerator == ACCELERATOR_HYBRID ? "X68000 Hybrid" :
  2899:                         currentModel.getName () +
  2900:                         (currentAccelerator == ACCELERATOR_XELLENT30 ? " with Xellent30" :
  2901:                          currentAccelerator == ACCELERATOR_060TURBO ? " with 060turbo" :
  2902:                          currentAccelerator == ACCELERATOR_060TURBOPRO ? " with 060turboPRO" : "")) +
  2903:                        " - " + PRG_TITLE + " version " + PRG_VERSION);
  2904:   }
  2905: 
  2906:   //frmStart ()
  2907:   //  フレームのイベントリスナーを設定して動作を開始する
  2908:   public static void frmStart () {
  2909: 
  2910:     //ウインドウリスナー
  2911:     //  ウインドウを開いたとき  activated,opened
  2912:     //  フォーカスを失ったとき  deactivated
  2913:     //  フォーカスを取得したとき  activated
  2914:     //  ウインドウをアイコン化したとき  iconified,[deactivated]
  2915:     //  ウインドウを元のサイズに戻したとき  deiconified,activated
  2916:     //  ウインドウを閉じたとき  closing,[deactivated],closed
  2917:     ComponentFactory.addListener (
  2918:       frmFrame,
  2919:       new WindowAdapter () {
  2920:         @Override public void windowActivated (WindowEvent we) {
  2921:           frmIsActive = true;
  2922:         }
  2923:         @Override public void windowClosing (WindowEvent we) {
  2924:           prgTini ();
  2925:         }
  2926:         @Override public void windowDeactivated (WindowEvent we) {
  2927:           frmIsActive = false;
  2928:           //Mouse.musSetSeamlessOn (true);  //フォーカスを失ったときはシームレスに切り替える
  2929:         }
  2930:       });
  2931: 
  2932:     //コンポーネントリスナー
  2933:     //  エクスクルーシブマウスモードのときに使うパネルの座標を得る
  2934:     //  全画面表示のON/OFFを行ったときcomponentMovedが呼ばれないことがあるのでcomponentResizedでもパネルの座標を得る
  2935:     ComponentFactory.addListener (
  2936:       frmFrame,
  2937:       new ComponentAdapter () {
  2938:         @Override public void componentMoved (ComponentEvent ce) {
  2939:           Point p = pnlPanel.getLocationOnScreen ();
  2940:           pnlGlobalX = p.x;
  2941:           pnlGlobalY = p.y;
  2942:         }
  2943:         @Override public void componentResized (ComponentEvent ce) {
  2944:           Point p = pnlPanel.getLocationOnScreen ();
  2945:           pnlGlobalX = p.x;
  2946:           pnlGlobalY = p.y;
  2947:         }
  2948:       });
  2949: 
  2950:   }  //frmStart()
  2951: 
  2952:   //frmSetFullscreenOn (on)
  2953:   //  全画面表示を設定する
  2954:   //  メニューアイテムは更新しないので必要ならば呼び出し側で更新すること
  2955:   public static void frmSetFullscreenOn (boolean on) {
  2956:     pnlFullscreenOn = on;
  2957:     //全画面表示を変更する
  2958:     if (on) {
  2959:       if (frmScreenDevice.getFullScreenWindow () != frmFrame) {  //自分が全画面表示でないとき
  2960:         frmFrame.getRootPane().setWindowDecorationStyle (JRootPane.NONE);  //飾り枠を消す
  2961:         frmScreenDevice.setFullScreenWindow (frmFrame);  //全画面表示に移行する
  2962:       }
  2963:     } else {
  2964:       if (frmScreenDevice.getFullScreenWindow () == frmFrame) {  //自分が全画面表示のとき
  2965:         frmScreenDevice.setFullScreenWindow (null);  //全画面表示を解除する
  2966:         frmFrame.getRootPane().setWindowDecorationStyle (JRootPane.FRAME);  //飾り枠を描く
  2967:       }
  2968:     }
  2969:     //全画面表示を変更するとコンポーネントイベントが発生する
  2970:     //コンポーネントリスナーで画面とキーボードの配置を再計算する
  2971:   }  //frmSetFullscreenOn(boolean)
  2972: 
  2973: 
  2974: 
  2975:   //========================================================================================
  2976:   //$$CLP クリップボード
  2977: 
  2978:   public static BufferedImage clpClipboardImage;  //コピーされるイメージ
  2979:   public static String clpClipboardString;  //コピーされる文字列
  2980:   public static Clipboard clpClipboard;  //クリップボード
  2981:   public static Transferable clpImageContents;  //イメージをコピーするときに渡すデータ
  2982:   public static Transferable clpStringContents;  //文字列をコピーするときに渡すデータ
  2983:   public static ClipboardOwner clpClipboardOwner;  //クリップボードオーナー。コピーするときにデータに付ける情報
  2984:   public static boolean clpIsClipboardOwner;  //true=クリップボードに入っているデータは自分がコピーした
  2985: 
  2986:   //clpMake ()
  2987:   //  クリップボードを作る
  2988:   public static void clpMake () {
  2989:     Toolkit toolkit = Toolkit.getDefaultToolkit ();
  2990:     clpClipboard = null;
  2991:     try {
  2992:       clpClipboard = toolkit.getSystemClipboard ();  //クリップボード
  2993:     } catch (Exception e) {
  2994:       return;
  2995:     }
  2996:     clpClipboardImage = null;  //コピーされるイメージ
  2997:     clpClipboardString = null;  //コピーされる文字列
  2998:     clpImageContents = new Transferable () {
  2999:       public Object getTransferData (DataFlavor flavor) throws UnsupportedFlavorException {
  3000:         if (flavor == DataFlavor.imageFlavor) {
  3001:           return clpClipboardImage;
  3002:         } else {
  3003:           throw new UnsupportedFlavorException (flavor);
  3004:         }
  3005:       }
  3006:       public DataFlavor[] getTransferDataFlavors () {
  3007:         return new DataFlavor[] { DataFlavor.imageFlavor };
  3008:       }
  3009:       public boolean isDataFlavorSupported (DataFlavor flavor) {
  3010:         return flavor == DataFlavor.imageFlavor;
  3011:       }
  3012:     };
  3013:     clpStringContents = new Transferable () {
  3014:       public Object getTransferData (DataFlavor flavor) throws UnsupportedFlavorException {
  3015:         if (flavor == DataFlavor.stringFlavor) {
  3016:           return clpClipboardString;
  3017:         } else {
  3018:           throw new UnsupportedFlavorException (flavor);
  3019:         }
  3020:       }
  3021:       public DataFlavor[] getTransferDataFlavors () {
  3022:         return new DataFlavor[] { DataFlavor.stringFlavor };
  3023:       }
  3024:       public boolean isDataFlavorSupported (DataFlavor flavor) {
  3025:         return flavor == DataFlavor.stringFlavor;
  3026:       }
  3027:     };
  3028:     clpIsClipboardOwner = false;  //自分はまだコピーしていない
  3029:     //クリップボードオーナー
  3030:     //  lostOwnership   クリップボードの所有者でなくなったとき
  3031:     clpClipboardOwner = new ClipboardOwner () {
  3032:       @Override public void lostOwnership (Clipboard clipboard, Transferable contents) {
  3033:         clpIsClipboardOwner = false;
  3034:       }
  3035:     };
  3036:     //フレーバーリスナー
  3037:     //  flavorsChanged  クリップボードのDataFlavorが変化したとき
  3038:     clpClipboard.addFlavorListener (new FlavorListener () {
  3039:       @Override public void flavorsChanged (FlavorEvent fe) {
  3040:         boolean available = false;
  3041:         try {
  3042:           available = clpClipboard.isDataFlavorAvailable (DataFlavor.stringFlavor);
  3043:         } catch (IllegalStateException ise) {
  3044:         }
  3045:         mnbPasteMenuItem.setEnabled (available);  //文字列ならば貼り付けできる
  3046:       }
  3047:     });
  3048:     if (!clpClipboard.isDataFlavorAvailable (DataFlavor.stringFlavor)) {  //文字列がコピーされていない
  3049:       mnbPasteMenuItem.setEnabled (false);  //貼り付け選択不可
  3050:     }
  3051:   }  //clpMake
  3052: 
  3053: 
  3054: 
  3055:   //========================================================================================
  3056:   //$$XT3 Xellent30
  3057:   //
  3058:   //  DIPSW
  3059:   //        1    2     ポートのアドレス
  3060:   //    0  OFF  OFF  $00EC0000~$00EC3FFF
  3061:   //    1  OFF  ON   $00EC4000~$00EC7FFF
  3062:   //    2  ON   OFF  $00EC8000~$00ECBFFF
  3063:   //    3  ON   ON   $00ECC000~$00ECFFFF
  3064:   //
  3065:   //  ポート
  3066:   //    FEDCBA9876543210
  3067:   //                 |||
  3068:   //                 ||bit0:メモリの位置。0=$00Bxxxxx,1=$00Fxxxxx
  3069:   //                 |bit1:メモリの有無。0=なし,1=あり
  3070:   //                 bit2:MPU。0=MC68000,1=MC68030
  3071:   //    +$3FFFまで同じワードが繰り返される
  3072:   //
  3073: 
  3074:   //DIPSW
  3075:   public static int xt3DIPSWRequest;  //DIPSW。0~3
  3076:   public static int xt3DIPSW;
  3077:   public static int xt3PortAddress;  //ポートのアドレス。0x00ec0000+(xt3DIPSW<<14)
  3078: 
  3079:   //メモリ
  3080:   public static int xt3MemorySizeRequest;  //メモリのサイズ。1<<18(256KB)または1<<20(1MB)
  3081:   public static int xt3MemorySize;
  3082:   public static boolean xt3MemoryEnabled;  //メモリの有無。false=なし,true=あり
  3083:   public static int xt3MemoryPosition;  //メモリの位置。xt3MemoryArray[0]のアドレス。11<<20または15<<20
  3084:   public static int xt3MemoryStart;  //メモリの開始アドレス。xt3MemoryPosition+(1<<20)-xt3MemorySize
  3085:   public static final byte[] xt3MemoryArray = new byte[1 << 20];  //メモリの内容の配列。常に1MB
  3086:   public static boolean xt3MemorySave;  //メモリの保存フラグ。true=保存する。常に1MBを保存・復元する
  3087: 
  3088:   //MPU
  3089:   public static int xt3SavedPC;  //MC68000のPC
  3090:   public static final int[] xt3SavedRn = new int[16];  //MC68000のRn
  3091: 
  3092:   //初期化
  3093:   public static void xt3Init () {
  3094: 
  3095:     //DIPSW
  3096:     xt3DIPSWRequest = Math.max (0, Math.min (3, Settings.sgsGetInt ("xt3dipsw")));  //メニューで変更できる
  3097:     xt3DIPSW = xt3DIPSWRequest;  //リセットで更新する
  3098: 
  3099:     //ポートのアドレス
  3100:     xt3PortAddress = 0x00ec0000 + (xt3DIPSW << 14);  //リセットで更新する
  3101: 
  3102:     //メモリのサイズ
  3103:     int memoryKB = Settings.sgsGetInt ("xt3memorykb");
  3104:     if (!(memoryKB == 1 << 8 || memoryKB == 1 << 10)) {
  3105:       memoryKB = 1 << 8;
  3106:     }
  3107:     xt3MemorySizeRequest = memoryKB << 10;  //メニューで変更できる
  3108:     xt3MemorySize = xt3MemorySizeRequest;  //リセットで更新する
  3109: 
  3110:     //メモリの有無
  3111:     xt3MemoryEnabled = false;  //リセットで更新する。ポートで変更できる
  3112: 
  3113:     //メモリの位置
  3114:     xt3MemoryPosition = 11 << 20;  //リセットで更新する。ポートで変更できる
  3115: 
  3116:     //メモリの開始アドレス
  3117:     xt3MemoryStart = xt3MemoryPosition + (1 << 20) - xt3MemorySize;  //リセットで更新する。ポートで変更できる
  3118: 
  3119:     //メモリの内容の配列
  3120:     //xt3MemoryArray = new byte[1 << 20];
  3121:     byte[] memoryArray = Settings.sgsGetData ("xt3memorydata");  //リセットでは更新しない。動作中に変化する
  3122:     Arrays.fill (xt3MemoryArray,  //array
  3123:                  (byte) 0);  //data
  3124:     if (memoryArray.length != 0) {  //復元するデータがある
  3125:       System.arraycopy (memoryArray, 0,  //from
  3126:                         xt3MemoryArray, 0,  //to
  3127:                         Math.min (memoryArray.length, xt3MemoryArray.length));  //length
  3128:       if (memoryArray.length < xt3MemoryArray.length) {
  3129:         Arrays.fill (xt3MemoryArray,  //array
  3130:                      memoryArray.length,  //from
  3131:                      xt3MemoryArray.length,  //to
  3132:                      (byte) 0);  //data
  3133:       }
  3134:     }
  3135: 
  3136:     //メモリの保存フラグ
  3137:     xt3MemorySave = Settings.sgsGetOnOff ("xt3memorysave");  //メニューで変更できる
  3138: 
  3139:     //MPU
  3140:     xt3SavedPC = 0;  //リセットで更新する
  3141:     //xt3SavedRn = new int[16];
  3142:     Arrays.fill (xt3SavedRn, 0);  //リセットで更新する
  3143: 
  3144:     xt3Reset ();
  3145:   }
  3146: 
  3147:   //後始末
  3148:   public static void xt3Tini () {
  3149: 
  3150:     //DIPSW
  3151:     Settings.sgsPutInt ("xt3dipsw", xt3DIPSW);  //メニューで変更できる
  3152: 
  3153:     //メモリのサイズ
  3154:     Settings.sgsPutInt ("xt3memorykb", xt3MemorySizeRequest >> 10);  //メニューで変更できる
  3155: 
  3156:     //メモリの内容の配列
  3157:     boolean zero = true;
  3158:     if (xt3MemorySave) {
  3159:       for (int i = 0; i < 1 << 20; i++) {
  3160:         if (xt3MemoryArray[i] != 0) {
  3161:           zero = false;
  3162:           break;
  3163:         }
  3164:       }
  3165:     }
  3166:     Settings.sgsCurrentMap.put ("xt3memorydata",
  3167:                                 zero ? "" :
  3168:                                 ByteArray.byaEncodeBase64 (ByteArray.byaEncodeGzip (xt3MemoryArray, 0, 1 << 20)));  //動作中に変化する
  3169: 
  3170:     //メモリの保存フラグ
  3171:     Settings.sgsPutOnOff ("xt3memorysave", xt3MemorySave);  //メニューで変更できる
  3172: 
  3173:   }
  3174: 
  3175:   //リセット
  3176:   public static void xt3Reset () {
  3177: 
  3178:     //ポートのアドレス
  3179:     xt3PortAddress = 0x00ec0000 + (xt3DIPSW << 14);  //リセットで更新する
  3180: 
  3181:     //メモリのサイズ
  3182:     xt3MemorySize = xt3MemorySizeRequest;  //リセットで更新する
  3183: 
  3184:     //メモリの有無
  3185:     xt3MemoryEnabled = false;  //リセットで更新する。ポートで変更できる
  3186: 
  3187:     //メモリの位置
  3188:     xt3MemoryPosition = 11 << 20;  //リセットで更新する。ポートで変更できる
  3189: 
  3190:     //メモリの開始アドレス
  3191:     xt3MemoryStart = xt3MemoryPosition + (1 << 20) - xt3MemorySize;  //リセットで更新する。ポートで変更できる
  3192: 
  3193:     //MPU
  3194:     xt3SavedPC = 0;  //リセットで更新する
  3195:     Arrays.fill (xt3SavedRn, 0);  //リセットで更新する
  3196: 
  3197:   }
  3198: 
  3199:   //リードワード
  3200:   public static int xt3PortRead () {
  3201:     return (currentIsSecond ? 4 : 0) | (xt3MemoryEnabled ? 2 : 0) | (xt3MemoryPosition == 11 << 20 ? 0 : 1);
  3202:   }
  3203: 
  3204:   //ライトワード
  3205:   public static void xt3PortWrite (int d) {
  3206:     boolean nextIsSecond = (d & 4) != 0;
  3207:     boolean memoryEnabled = (d & 2) != 0;
  3208:     int memoryPosition = (d & 1) == 0 ? 11 << 20 : 15 << 20;
  3209: 
  3210:     if (xt3MemoryEnabled != memoryEnabled ||
  3211:         xt3MemoryPosition != memoryPosition) {  //メモリの有無または位置が変更された
  3212:       if (xt3MemoryEnabled) {  //元の位置から取り除く
  3213:         if (xt3MemoryPosition == 11 << 20) {  //$00Bxxxxx
  3214:           if (MainMemory.mmrMemorySizeCurrent < 12 << 20) {  //メインメモリが12MBない
  3215:             busSuper (MemoryMappedDevice.MMD_NUL, (12 << 20) - xt3MemorySize, 12 << 20);  //空きに戻す
  3216:           } else {  //メインメモリが12MBある
  3217:             busUser (MemoryMappedDevice.MMD_MMR, (12 << 20) - xt3MemorySize, 12 << 20);  //メインメモリに戻す
  3218:           }
  3219:         } else {  //$00Fxxxxx
  3220:           busSuper (MemoryMappedDevice.MMD_ROM, (16 << 20) - xt3MemorySize, 16 << 20);  //ROMに戻す
  3221:         }
  3222:       }
  3223:       xt3MemoryEnabled = memoryEnabled;  //メモリの有無
  3224:       xt3MemoryPosition = memoryPosition;  //メモリの位置
  3225:       if (xt3MemoryEnabled) {  //新しい位置に配置する
  3226:         if (xt3MemoryPosition == 11 << 20) {  //$00Bxxxxx
  3227:           busUser (MemoryMappedDevice.MMD_XTM, (12 << 20) - xt3MemorySize, 12 << 20);  //メモリを配置する
  3228:         } else {  //$00Fxxxxx
  3229:           busUser (MemoryMappedDevice.MMD_XTM, (16 << 20) - xt3MemorySize, 16 << 20);  //メモリを配置する
  3230:         }
  3231:       }
  3232:     }
  3233: 
  3234:     if (currentIsSecond != nextIsSecond) {  //MPUが変わる
  3235: 
  3236:       if (nextIsSecond) {  //MC68000→MC68EC030
  3237: 
  3238:         //HALTしたときのPCとRnを保存する
  3239:         xt3SavedPC = regPC;
  3240:         System.arraycopy (regRn, 0, xt3SavedRn, 0, 16);
  3241: 
  3242:         //MC68000を停止する
  3243:         if (mpuTask != null) {
  3244:           mpuClockLimit = 0L;
  3245:           System.out.println (Multilingual.mlnJapanese ?
  3246:                               Model.MPU_NAMES[currentFirstMPU] + " を停止します" :
  3247:                               Model.MPU_NAMES[currentFirstMPU] + " stops");
  3248:           mpuTask.cancel ();
  3249:           mpuTask = null;
  3250:         }
  3251: 
  3252:         //MC68EC030を起動する
  3253:         tmrTimer.schedule (new TimerTask () {
  3254:           @Override public void run () {
  3255: 
  3256:             //MPU
  3257:             currentIsSecond = true;
  3258:             currentMPU = currentSecondMPU;
  3259:             mpuSetCurrentClock (specifiedSecondClock);
  3260: 
  3261:             if (MC68EC030.M30_DIV_ZERO_V_FLAG) {
  3262:               MC68EC030.m30DivZeroVFlag = false;
  3263:             }
  3264: 
  3265:             RegisterList.drpSetMPU ();
  3266:             mpuSFC = mpuDFC = mpuCACR = mpuBUSCR = mpuUSP = mpuVBR = mpuCAAR = mpuMSP = mpuISP = 0;
  3267:             mpuPCR = 0x04300500 | MPU_060_REV << 8;
  3268:             MC68060.mmuReset ();  //TCR,ITT0,ITT1,DTT0,DTT1,URP,SRP。060→000/030のときアドレス変換をOFFにする必要がある
  3269:             //MC68EC030
  3270:             mpuIgnoreAddressError = true;
  3271:             fpuBox = fpuMotherboardCoprocessor;
  3272:             if (currentFPU == 2) {
  3273:               fpuBox.epbSetMC68882 ();
  3274:             } else {
  3275:               fpuBox.epbSetMC68881 ();
  3276:             }
  3277:             if (currentTriplePrecision) {
  3278:               fpuBox.epbSetTriple ();
  3279:             } else {
  3280:               fpuBox.epbSetExtended ();
  3281:             }
  3282:             fpuBox.epbReset ();
  3283:             fpuFPn = fpuBox.epbFPn;
  3284:             mpuCacheOn = (mpuCACR & 0x00000101) != 0;
  3285:             mpuSetWait ();
  3286:             //
  3287:             regSRT1 = regSRT0 = 0;
  3288:             regSRS = REG_SR_S;
  3289:             regSRM = 0;
  3290:             regSRI = REG_SR_I;
  3291:             regCCR = 0;
  3292:             Arrays.fill (regRn, 0);
  3293:             //PCとSSPをRAMから読み出す
  3294:             regRn[15] = MainMemory.mmrRls (0x00000000);
  3295:             regPC = MainMemory.mmrRls (0x00000004);
  3296:             //割り込み
  3297:             mpuIMR = 0;
  3298:             mpuIRR = 0;
  3299:             if (MC68901.MFP_DELAYED_INTERRUPT) {
  3300:               mpuDIRR = 0;
  3301:             }
  3302:             mpuISR = 0;
  3303:             //動作開始
  3304:             mpuStart ();
  3305:           }
  3306:         }, TMR_DELAY);
  3307: 
  3308:       } else {  //MC68EC030→MC68000
  3309: 
  3310:         //MC68EC030を停止する
  3311:         if (mpuTask != null) {
  3312:           mpuClockLimit = 0L;
  3313:           System.out.println (Multilingual.mlnJapanese ? "MC68EC030 を停止します" : "MC68EC030 stops");
  3314:           mpuTask.cancel ();
  3315:           mpuTask = null;
  3316:         }
  3317: 
  3318:         //MC68000を起動する
  3319:         tmrTimer.schedule (new TimerTask () {
  3320:           @Override public void run () {
  3321: 
  3322:             //MPU
  3323:             currentIsSecond = false;
  3324:             currentMPU = currentFirstMPU;
  3325:             mpuSetCurrentClock (specifiedFirstClock);
  3326: 
  3327:             RegisterList.drpSetMPU ();
  3328:             mpuSFC = mpuDFC = mpuCACR = mpuBUSCR = mpuUSP = mpuVBR = mpuCAAR = mpuMSP = mpuISP = 0;
  3329:             mpuPCR = 0x04300500 | MPU_060_REV << 8;
  3330:             MC68060.mmuReset ();  //TCR,ITT0,ITT1,DTT0,DTT1,URP,SRP。060→000/030のときアドレス変換をOFFにする必要がある
  3331:             //MC68000
  3332:             mpuIgnoreAddressError = false;
  3333:             mpuCacheOn = false;
  3334:             mpuSetWait ();
  3335:             //
  3336:             regSRT1 = regSRT0 = 0;
  3337:             regSRS = REG_SR_S;
  3338:             regSRM = 0;
  3339:             regSRI = REG_SR_I;
  3340:             regCCR = 0;
  3341:             //HALTしたときのPCとRnを復元する
  3342:             regPC = xt3SavedPC;
  3343:             System.arraycopy (xt3SavedRn, 0, regRn, 0, 16);
  3344:             //割り込み
  3345:             mpuIMR = 0;
  3346:             mpuIRR = 0;
  3347:             if (MC68901.MFP_DELAYED_INTERRUPT) {
  3348:               mpuDIRR = 0;
  3349:             }
  3350:             mpuISR = 0;
  3351:             //動作開始
  3352:             mpuStart ();
  3353:           }
  3354:         }, TMR_DELAY);
  3355: 
  3356:       }
  3357:     }
  3358:   }
  3359: 
  3360: 
  3361: 
  3362:   //========================================================================================
  3363:   //$$MDL 機種
  3364: 
  3365:   public static JMenu mdlMenu;  //メニュー
  3366: 
  3367:   public static JRadioButtonMenuItem mdlShodaiMenuItem;
  3368:   public static JRadioButtonMenuItem mdlACEMenuItem;
  3369:   public static JRadioButtonMenuItem mdlEXPERTMenuItem;
  3370:   public static JRadioButtonMenuItem mdlPROMenuItem;
  3371:   public static JRadioButtonMenuItem mdlSUPERMenuItem;
  3372:   public static JRadioButtonMenuItem mdlXVIMenuItem;
  3373:   public static JRadioButtonMenuItem mdlXellent30MenuItem;
  3374:   public static JRadioButtonMenuItem mdlCompactMenuItem;
  3375:   public static JRadioButtonMenuItem mdlHybridMenuItem;
  3376:   public static JRadioButtonMenuItem mdl060turboPROMenuItem;
  3377:   public static JRadioButtonMenuItem mdlX68030MenuItem;
  3378:   public static JRadioButtonMenuItem mdl030CompactMenuItem;
  3379:   public static JRadioButtonMenuItem mdl060turboMenuItem;
  3380:   public static JCheckBoxMenuItem mdlMC68010MenuItem;
  3381: 
  3382:   public static JRadioButtonMenuItem fpuMenuItem0;
  3383:   public static JRadioButtonMenuItem fpuMenuItem1;
  3384:   public static JRadioButtonMenuItem fpuMenuItem2;
  3385:   public static JCheckBoxMenuItem fpuMenuItem3;
  3386: 
  3387:   //アクセラレータ
  3388:   public static final int ACCELERATOR_HYBRID      = 1;  //Compact+33.3MHz+IPLROM 1.6
  3389:   public static final int ACCELERATOR_XELLENT30   = 2;  //XVI+secondMPU
  3390:   public static final int ACCELERATOR_060TURBO    = 3;  //X68030+MC68060
  3391:   public static final int ACCELERATOR_060TURBOPRO = 4;  //PRO+MC68060
  3392:   public static final double MHZ_HYBRID_VALUE = 100.0 / 3.0;  //Hybridの動作周波数。33.3MHz
  3393:   public static final String MHZ_HYBRID_STRING = "33.3";
  3394:   public static final double MHZ_060TURBO_VALUE = 50.0;  //060turbo/060turboPROの動作周波数
  3395:   public static final String MHZ_060TURBO_STRING = "50";
  3396: 
  3397:   //指定された値
  3398:   //  機種とアクセラレータ
  3399:   public static Model specifiedModel;  //指定された機種
  3400:   public static int specifiedAccelerator;  //指定されたアクセラレータ
  3401:   //  MPU
  3402:   public static boolean specifiedIsSecond;  //指定されたMPUは2番目か
  3403:   public static int specifiedFirstMPU;  //指定された1番目のMPU。Model.MPU_MC68000~Model.MPU_MC68060
  3404:   public static int specifiedSecondMPU;  //指定された2番目のMPU。Model.MPU_MC68000~Model.MPU_MC68060
  3405:   public static int specifiedMPU;  //指定されたMPU。specifiedIsSecond?specifiedSecondMPU:specifiedFirstMPU
  3406:   //  クロック(MHz)
  3407:   public static double specifiedFirstClock;  //指定された1番目のクロック(MHz)
  3408:   public static double specifiedSecondClock;  //指定された2番目のクロック(MHz)
  3409:   public static double specifiedClock;  //指定されたクロック(MHz)。specifiedIsSecond?specifiedSecondClock:specifiedFirstClock
  3410:   //  FPUまたはFPCP
  3411:   public static int specifiedFPU;  //指定されたFPUまたはFPCP。0=なし,1=68881,2=68882
  3412:   public static boolean specifiedTriplePrecision;  //指定された三倍精度か
  3413:   public static boolean specifiedFullSpecification;  //指定されたフルスペックか
  3414: 
  3415:   //現在の値
  3416:   //  機種とアクセラレータ
  3417:   public static Model currentModel;  //現在の機種
  3418:   public static int currentAccelerator;  //現在のアクセラレータ
  3419:   //  MPU
  3420:   public static boolean currentIsSecond;  //現在のMPUは2番目か
  3421:   public static int currentFirstMPU;  //現在の1番目のMPU。Model.MPU_MC68000~Model.MPU_MC68060
  3422:   public static int currentSecondMPU;  //現在の2番目のMPU。Model.MPU_MC68000~Model.MPU_MC68060
  3423:   public static int currentMPU;  //現在のMPU。currentIsSecond?currentSecondMPU:currentFirstMPU
  3424:   //  クロック(MHz)は指定された値を用いる
  3425:   //  FPUまたはFPCP
  3426:   public static int currentFPU;  //現在のFPUまたはFPCP。0=なし,1=68881,2=68882
  3427:   public static boolean currentTriplePrecision;  //現在は三倍精度か
  3428:   public static boolean currentFullSpecification;  //現在はフルスペックか
  3429: 
  3430:   //mdlInit ()
  3431:   //  機種の指定を読み取る
  3432:   public static void mdlInit () {
  3433: 
  3434:     //機種とアクセラレータ
  3435:     specifiedModel = Model.COMPACT;
  3436:     specifiedAccelerator = ACCELERATOR_HYBRID;
  3437:     {
  3438:       String paramModel = Settings.sgsGetString ("model");
  3439:       switch (paramModel.toLowerCase ()) {
  3440:       case "":
  3441:       case "none":
  3442:       case "hybrid":
  3443:         specifiedModel = Model.COMPACT;
  3444:         specifiedAccelerator = ACCELERATOR_HYBRID;
  3445:         break;
  3446:       case "xellent30":
  3447:         specifiedModel = Model.XVI;
  3448:         specifiedAccelerator = ACCELERATOR_XELLENT30;
  3449:         break;
  3450:       case "060turbo":
  3451:         specifiedModel = Model.X68030;
  3452:         specifiedAccelerator = ACCELERATOR_060TURBO;
  3453:         break;
  3454:       case "060turbopro":
  3455:         specifiedModel = Model.PRO;
  3456:         specifiedAccelerator = ACCELERATOR_060TURBOPRO;
  3457:         break;
  3458:       default:
  3459:         Model model = Model.fromTypeOrSynonym (paramModel);
  3460:         if (model != null) {
  3461:           specifiedModel = model;
  3462:           specifiedAccelerator = 0;
  3463:         } else {
  3464:           System.out.println (Multilingual.mlnJapanese ?
  3465:                               paramModel + " は不明な機種です" :
  3466:                               paramModel + " is unknown model");
  3467:           specifiedModel = Model.COMPACT;
  3468:           specifiedAccelerator = ACCELERATOR_HYBRID;
  3469:         }
  3470:       }
  3471:     }
  3472:     //MPU
  3473:     specifiedIsSecond = false;
  3474:     specifiedFirstMPU = specifiedModel.getMPU ();
  3475:     specifiedSecondMPU = Model.MPU_MC68EC030;
  3476:     {
  3477:       String[] paramMPUs = Settings.sgsGetString ("mpu").split (",");
  3478:       for (int i = 0; i < 2; i++) {
  3479:         int mpu = 0;
  3480:         String paramMPU = i < paramMPUs.length ? paramMPUs[i] : "";
  3481:         switch (paramMPU) {
  3482:         case "":
  3483:         case "none":
  3484:         case "-1":
  3485:           mpu = (i == 0 ?
  3486:                  (specifiedAccelerator == ACCELERATOR_060TURBO ||
  3487:                   specifiedAccelerator == ACCELERATOR_060TURBOPRO ? Model.MPU_MC68060 :
  3488:                   specifiedModel.getMPU ()) :
  3489:                  Model.MPU_MC68EC030);
  3490:           break;
  3491:         case "0":
  3492:         case "68000":
  3493:         case "mc68000":
  3494:           mpu = Model.MPU_MC68000;
  3495:           break;
  3496:         case "1":
  3497:         case "68010":
  3498:         case "mc68010":
  3499:           mpu = Model.MPU_MC68010;
  3500:           break;
  3501:           //case "2":
  3502:           //case "68020":
  3503:           //case "mc68020":
  3504:           //  specifiedFirstMPU = Model.MPU_MC68020;
  3505:           //  break;
  3506:         case "3":
  3507:         case "68ec030":
  3508:         case "mc68ec030":
  3509:           mpu = Model.MPU_MC68EC030;
  3510:           break;
  3511:           //case "68030":
  3512:           //case "mc68030":
  3513:           //  mpu = Model.MPU_MC68030;
  3514:           //  break;
  3515:           //case "68lc040":
  3516:           //case "mc68lc040":
  3517:           //  mpu = Model.MPU_MC68LC040;
  3518:           //  break;
  3519:           //case "4":
  3520:           //case "68040":
  3521:           //case "mc68040":
  3522:           //  mpu = Model.MPU_MC68040;
  3523:           //  break;
  3524:           //case "68lc060":
  3525:           //case "mc68lc060":
  3526:           //  mpu = Model.MPU_MC68LC060;
  3527:           //  break;
  3528:         case "6":
  3529:         case "68060":
  3530:         case "mc68060":
  3531:           mpu = Model.MPU_MC68060;
  3532:           break;
  3533:         default:
  3534:           Model model = Model.fromTypeOrSynonym (paramMPU);
  3535:           if (model != null) {
  3536:             mpu = model.getMPU ();
  3537:           } else {
  3538:             System.out.println (Multilingual.mlnJapanese ?
  3539:                                 paramMPU + " は不明な MPU です" :
  3540:                                 paramMPU + " is unknown MPU");
  3541:             mpu = specifiedModel.getMPU ();
  3542:           }
  3543:         }  //switch
  3544:         if (i == 0) {
  3545:           specifiedFirstMPU = mpu;
  3546:         } else {
  3547:           specifiedSecondMPU = mpu;
  3548:         }
  3549:       }  //for i
  3550:     }
  3551:     specifiedMPU = specifiedIsSecond ? specifiedSecondMPU : specifiedFirstMPU;
  3552:     //クロック(MHz)
  3553:     specifiedFirstClock = specifiedModel.getClock ();
  3554:     specifiedSecondClock = specifiedFirstClock * 2.0;
  3555:     {
  3556:       String[] paramClocks = Settings.sgsGetString ("clock").split (",");
  3557:       for (int i = 0; i < 2; i++) {
  3558:         double clock = 0.0;
  3559:         String paramClock = i < paramClocks.length ? paramClocks[i] : "";
  3560:         switch (paramClock.toLowerCase ()) {
  3561:         case "":
  3562:         case "none":
  3563:         case "-1":
  3564:           clock = (i == 0 ?
  3565:                    (specifiedAccelerator == ACCELERATOR_HYBRID ? MHZ_HYBRID_VALUE :  //33.3MHz
  3566:                     specifiedAccelerator == ACCELERATOR_060TURBO ||
  3567:                     specifiedAccelerator == ACCELERATOR_060TURBOPRO ? MHZ_060TURBO_VALUE :
  3568:                     specifiedModel.getClock ()) :
  3569:                    specifiedFirstClock * 2.0);
  3570:           break;
  3571:         case "hybrid":
  3572:           clock = MHZ_HYBRID_VALUE;  //33.3MHz
  3573:           break;
  3574:         case "060turbo":
  3575:         case "060turbopro":
  3576:           clock = MHZ_060TURBO_VALUE;
  3577:           break;
  3578:         case "16.7":
  3579:         case "xellent30":
  3580:           clock = 50.0 / 3.0;  //16.7MHz
  3581:           break;
  3582:         case "33.3":
  3583:           clock = 100.0 / 3.0;  //33.3MHz
  3584:           break;
  3585:         case "66.7":
  3586:           clock = 200.0 / 3.0;  //66.7MHz
  3587:           break;
  3588:         default:
  3589:           if (paramClock.matches ("^(?:" +
  3590:                                   "[-+]?" +  //符号
  3591:                                   "(?:[0-9]+(?:\\.[0-9]*)?|\\.[0-9]+)" +  //仮数部
  3592:                                   "(?:[Ee][-+]?[0-9]+)?" +  //指数部
  3593:                                   ")$")) {
  3594:             double d = Double.parseDouble (paramClock);
  3595:             if (1.0 <= d && d <= 1000.0) {
  3596:               clock = d;
  3597:             }
  3598:           } else {
  3599:             System.out.println (Multilingual.mlnJapanese ?
  3600:                                 paramClock + " は不明な動作周波数です" :
  3601:                                 paramClock + " is unknown clock frequency");
  3602:             clock = specifiedModel.getClock ();
  3603:           }
  3604:         }  //switch
  3605:         if (i == 0) {
  3606:           specifiedFirstClock = clock;
  3607:         } else {
  3608:           specifiedSecondClock = clock;
  3609:         }
  3610:       }  //for i
  3611:     }
  3612:     specifiedClock = specifiedIsSecond ? specifiedSecondClock : specifiedFirstClock;
  3613:     //FPUとFPCP
  3614:     specifiedFPU = 0;
  3615:     specifiedTriplePrecision = false;
  3616:     specifiedFullSpecification = false;
  3617:     {
  3618:       int paramFPUMode = fmtParseInt (Settings.sgsGetString ("fpumode"), 0, 0, 2, 0);  //0=なし,1=拡張精度,2=三倍精度
  3619:       if (paramFPUMode == 0) {  //なし
  3620:         specifiedFPU = 0;
  3621:         specifiedTriplePrecision = false;
  3622:       } else if (paramFPUMode == 1) {  //拡張精度
  3623:         specifiedFPU = Model.FPU_MC68882;
  3624:         specifiedTriplePrecision = false;
  3625:       } else if (paramFPUMode == 2) {  //三倍精度
  3626:         specifiedFPU = Model.FPU_MC68882;
  3627:         specifiedTriplePrecision = true;
  3628:       }
  3629:       specifiedFullSpecification = Settings.sgsGetOnOff ("fullspecfpu");
  3630:     }
  3631: 
  3632:     //現在の値にコピーしておく
  3633:     //  機種とアクセラレータ
  3634:     currentModel = specifiedModel;
  3635:     currentAccelerator = specifiedAccelerator;
  3636:     //  MPU
  3637:     currentIsSecond = specifiedIsSecond;
  3638:     currentFirstMPU = specifiedFirstMPU;
  3639:     currentSecondMPU = specifiedSecondMPU;
  3640:     currentMPU = specifiedMPU;
  3641:     //  クロック(MHz)
  3642:     //  FPUまたはFPCP
  3643:     currentFPU = specifiedFPU;
  3644:     currentTriplePrecision = specifiedTriplePrecision;
  3645:     currentFullSpecification = specifiedFullSpecification;
  3646: 
  3647:     //任意の負荷率
  3648:     mpuUtilOn = Settings.sgsGetOnOff ("util");  //任意の負荷率
  3649:     mpuUtilRatio = fmtParseInt (Settings.sgsGetString ("ratio"), 0, 1, 100, 100);  //任意の負荷率
  3650:     //任意の周波数
  3651:     mpuArbFreqMHz = fmtParseInt (Settings.sgsGetString ("mhz"), 0, 1, 1000, 100);
  3652:     if (mpuUtilOn) {
  3653:       mpuArbFreqOn = false;
  3654:     } else {
  3655:       mpuArbFreqOn = !(specifiedClock == 10.0 ||
  3656:                        specifiedClock == 50.0 / 3.0 ||  //16.7MHz
  3657:                        specifiedClock == 25.0 ||
  3658:                        specifiedClock == 100.0 / 3.0 ||  //33.3MHz
  3659:                        specifiedClock == 50.0 ||
  3660:                        specifiedClock == 200.0 / 3.0 ||  //66.7MHz
  3661:                        specifiedClock == 75.0 ||
  3662:                        specifiedClock == 100.0);
  3663:       if (mpuArbFreqOn) {
  3664:         mpuArbFreqMHz = (int) specifiedClock;
  3665:       }
  3666:     }
  3667: 
  3668:     //ウェイトサイクル
  3669:     mpuROMWaitCycles = 0;
  3670:     mpuRAMWaitCycles = 0;
  3671:     mpuCacheOn = false;
  3672:     //mpuNoWaitTime = new WaitTime ();
  3673:     mpuNoWaitTime.ram = 0;
  3674:     mpuNoWaitTime.gvram = 0;
  3675:     mpuNoWaitTime.tvram = 0;
  3676:     mpuNoWaitTime.crtc = 0;
  3677:     mpuNoWaitTime.palet = 0;
  3678:     mpuNoWaitTime.vicon = 0;
  3679:     mpuNoWaitTime.dmac = 0;
  3680:     mpuNoWaitTime.mfp = 0;
  3681:     mpuNoWaitTime.rtc = 0;
  3682:     mpuNoWaitTime.prnport = 0;
  3683:     mpuNoWaitTime.sysport = 0;
  3684:     mpuNoWaitTime.opm = 0;
  3685:     mpuNoWaitTime.adpcm = 0;
  3686:     mpuNoWaitTime.fdc = 0;
  3687:     mpuNoWaitTime.fdd = 0;
  3688:     mpuNoWaitTime.hdc = 0;
  3689:     mpuNoWaitTime.scc = 0;
  3690:     mpuNoWaitTime.ppi = 0;
  3691:     mpuNoWaitTime.ioi = 0;
  3692:     mpuNoWaitTime.sprc = 0;
  3693:     mpuNoWaitTime.sram = 0;
  3694:     mpuNoWaitTime.rom = 0;
  3695:     mpuNoWaitTime.ramlong = mpuNoWaitTime.ram << 1;
  3696:     mpuNoWaitTime.romlong = mpuNoWaitTime.rom << 1;
  3697:     //dmaNoWaitTime = new WaitTime ();
  3698:     dmaNoWaitTime.ram = 0;
  3699:     dmaNoWaitTime.gvram = 0;
  3700:     dmaNoWaitTime.tvram = 0;
  3701:     dmaNoWaitTime.crtc = 0;
  3702:     dmaNoWaitTime.palet = 0;
  3703:     dmaNoWaitTime.vicon = 0;
  3704:     dmaNoWaitTime.dmac = 0;
  3705:     dmaNoWaitTime.mfp = 0;
  3706:     dmaNoWaitTime.rtc = 0;
  3707:     dmaNoWaitTime.prnport = 0;
  3708:     dmaNoWaitTime.sysport = 0;
  3709:     dmaNoWaitTime.opm = 0;
  3710:     dmaNoWaitTime.adpcm = 0;
  3711:     dmaNoWaitTime.fdc = 0;
  3712:     dmaNoWaitTime.fdd = 0;
  3713:     dmaNoWaitTime.hdc = 0;
  3714:     dmaNoWaitTime.scc = 0;
  3715:     dmaNoWaitTime.ppi = 0;
  3716:     dmaNoWaitTime.ioi = 0;
  3717:     dmaNoWaitTime.sprc = 0;
  3718:     dmaNoWaitTime.sram = 0;
  3719:     dmaNoWaitTime.rom = 0;
  3720:     dmaNoWaitTime.ramlong = dmaNoWaitTime.ram << 1;
  3721:     dmaNoWaitTime.romlong = dmaNoWaitTime.rom << 1;
  3722:     //mpuWaitTime = new WaitTime ();
  3723:     //dmaWaitTime = new WaitTime ();
  3724:     busWaitCyclesRequest = Settings.sgsGetOnOff ("waitcycles");
  3725:     busWaitCycles = busWaitCyclesRequest;
  3726:     busWaitTime = busWaitCycles ? mpuWaitTime : mpuNoWaitTime;
  3727: 
  3728:   }  //mdlInit()
  3729: 
  3730:   public static void mdlTini () {
  3731:     //機種とアクセラレータ
  3732:     Settings.sgsPutString ("model",
  3733:                            specifiedAccelerator == ACCELERATOR_HYBRID ? "Hybrid" :
  3734:                            specifiedAccelerator == ACCELERATOR_XELLENT30 ? "Xellent30" :
  3735:                            specifiedAccelerator == ACCELERATOR_060TURBO ? "060turbo" :
  3736:                            specifiedAccelerator == ACCELERATOR_060TURBOPRO ? "060turboPRO" :
  3737:                            specifiedModel.getSynonym () != null ? specifiedModel.getSynonym () :
  3738:                            specifiedModel.getType ());
  3739:     //MPU
  3740:     //  機種のデフォルトと同じときは省略する
  3741:     int defaultFirstMPU = (specifiedAccelerator == ACCELERATOR_060TURBO ||
  3742:                            specifiedAccelerator == ACCELERATOR_060TURBOPRO ? Model.MPU_MC68060 :
  3743:                            specifiedModel.getMPU ());
  3744:     int defaultSecondMPU = Model.MPU_MC68EC030;
  3745:     Settings.sgsPutString ("mpu",
  3746:                            (specifiedFirstMPU == defaultFirstMPU ? "" :
  3747:                             Model.mpuNameOf (specifiedFirstMPU)) +
  3748:                            (specifiedSecondMPU == defaultSecondMPU ? "" :
  3749:                             "," + Model.mpuNameOf (specifiedSecondMPU)));
  3750:     //クロック
  3751:     //  機種のデフォルトと同じときは省略する
  3752:     //  16.7MHzと33.3MHzは機種名で書くと正確に保存できる
  3753:     //  現在のクロックを保存する
  3754:     double defaultFirstClock = (specifiedAccelerator == ACCELERATOR_HYBRID ? MHZ_HYBRID_VALUE :  //33.3MHz
  3755:                                 specifiedAccelerator == ACCELERATOR_060TURBO ||
  3756:                                 specifiedAccelerator == ACCELERATOR_060TURBOPRO ? MHZ_060TURBO_VALUE :
  3757:                                 specifiedModel.getClock ());
  3758:     double defaultSecondClock = defaultFirstClock * 2.0;
  3759:     Settings.sgsPutString ("clock",
  3760:                            (specifiedFirstClock == defaultFirstClock ? "" :
  3761:                             specifiedFirstClock == 50.0 / 3.0 ? "16.7" :  //16.7MHz
  3762:                             specifiedFirstClock == 100.0 / 3.0 ? "33.3" :  //33.3MHz
  3763:                             specifiedFirstClock == 200.0 / 3.0 ? "66.7" :  //66.7MHz
  3764:                             String.valueOf ((int) specifiedFirstClock)) +
  3765:                            (specifiedSecondClock == defaultSecondClock ? "" :
  3766:                             "," + (specifiedSecondClock == 50.0 / 3.0 ? "16.7" :  //16.7MHz
  3767:                                    specifiedSecondClock == 100.0 / 3.0 ? "33.3" :  //33.3MHz
  3768:                                    specifiedSecondClock == 200.0 / 3.0 ? "66.7" :  //66.7MHz
  3769:                                    String.valueOf ((int) specifiedSecondClock))));
  3770:     //FPUとFPCP
  3771:     Settings.sgsPutInt ("fpumode",
  3772:                         specifiedFPU == 0 ? 0 :  //なし
  3773:                         !specifiedTriplePrecision ? 1 :  //拡張精度
  3774:                         2);  //三倍精度
  3775:     Settings.sgsPutOnOff ("fullspecfpu",
  3776:                           specifiedFullSpecification);  //フルスペック
  3777:     //任意の負荷率
  3778:     Settings.sgsPutOnOff ("util",
  3779:                           mpuUtilOn);
  3780:     Settings.sgsPutString ("ratio",
  3781:                            String.valueOf (mpuUtilRatio));
  3782:     //任意の周波数
  3783:     Settings.sgsPutString ("mhz",
  3784:                            String.valueOf (mpuArbFreqMHz));
  3785:     //ウェイトサイクル
  3786:     Settings.sgsPutOnOff ("waitcycles", busWaitCyclesRequest);
  3787:   }
  3788: 
  3789:   public static void mdlMakeMenu () {
  3790: 
  3791:     //アクションリスナー
  3792:     ActionListener listener = new ActionListener () {
  3793:       @Override public void actionPerformed (ActionEvent ae) {
  3794:         Object source = ae.getSource ();
  3795:         switch (ae.getActionCommand ()) {
  3796:         case "X68000 (10MHz)":
  3797:           mdlRequestModel (Model.SHODAI, 0);
  3798:           mpuReset (-1, -1);
  3799:           break;
  3800:         case "X68000 ACE (10MHz)":
  3801:           mdlRequestModel (Model.ACE, 0);
  3802:           mpuReset (-1, -1);
  3803:           break;
  3804:         case "X68000 EXPERT (10MHz)":
  3805:           mdlRequestModel (Model.EXPERT, 0);
  3806:           mpuReset (-1, -1);
  3807:           break;
  3808:         case "X68000 PRO (10MHz)":
  3809:           mdlRequestModel (Model.PRO, 0);
  3810:           mpuReset (-1, -1);
  3811:           break;
  3812:         case "X68000 SUPER (10MHz)":
  3813:           mdlRequestModel (Model.SUPER, 0);
  3814:           mpuReset (-1, -1);
  3815:           break;
  3816:         case "X68000 XVI (16.7MHz)":
  3817:           mdlRequestModel (Model.XVI, 0);
  3818:           mpuReset (-1, -1);
  3819:           break;
  3820:         case "X68000 Compact (16.7MHz)":
  3821:           mdlRequestModel (Model.COMPACT, 0);
  3822:           mpuReset (-1, -1);
  3823:           break;
  3824:           //
  3825:         case "X68030 (25MHz)":
  3826:           mdlRequestModel (Model.X68030, 0);
  3827:           mpuReset (-1, -1);
  3828:           break;
  3829:         case "X68030 Compact (25MHz)":
  3830:           mdlRequestModel (Model.X68030COMPACT, 0);
  3831:           mpuReset (-1, -1);
  3832:           break;
  3833:           //
  3834:         case "X68000 Hybrid (" + MHZ_HYBRID_STRING + "MHz)":
  3835:           mdlRequestModel (Model.COMPACT, ACCELERATOR_HYBRID);
  3836:           mpuReset (-1, -1);
  3837:           break;
  3838:         case "Xellent30 (33.3MHz)":
  3839:           mdlRequestModel (Model.XVI, ACCELERATOR_XELLENT30);
  3840:           mpuReset (-1, -1);
  3841:           break;
  3842:         case "060turbo (" + MHZ_060TURBO_STRING + "MHz)":
  3843:           mdlRequestModel (Model.X68030, ACCELERATOR_060TURBO);
  3844:           mpuReset (-1, -1);
  3845:           break;
  3846:         case "060turboPRO (" + MHZ_060TURBO_STRING + "MHz)":
  3847:           mdlRequestModel (Model.PRO, ACCELERATOR_060TURBOPRO);
  3848:           mpuReset (-1, -1);
  3849:           break;
  3850:           //
  3851:         case "MC68010":
  3852:           //((JCheckBoxMenuItem) source).isSelected ()
  3853:           break;
  3854: 
  3855:         case "No FPU":  //FPUなし
  3856:           specifiedFPU = 0;
  3857:           specifiedTriplePrecision = false;
  3858:           break;
  3859:         case "Extended precision (19 digit)":  //拡張精度 (19 桁)
  3860:           specifiedFPU = Model.FPU_MC68882;
  3861:           specifiedTriplePrecision = false;
  3862:           break;
  3863:         case "Triple precision (24 digit)":  //三倍精度 (24 桁)
  3864:           specifiedFPU = Model.FPU_MC68882;
  3865:           specifiedTriplePrecision = true;
  3866:           break;
  3867:         case "Full specification FPU":  //フルスペック FPU
  3868:           specifiedFullSpecification = ((JCheckBoxMenuItem) source).isSelected ();
  3869:           break;
  3870: 
  3871:         }
  3872:       }
  3873:     };
  3874: 
  3875:     //メニュー
  3876:     ButtonGroup modelGroup = new ButtonGroup ();
  3877:     mdlMenu = Multilingual.mlnText (
  3878:       ComponentFactory.createMenu (
  3879:         "Change the model and reset",
  3880:         mdlShodaiMenuItem = ComponentFactory.createRadioButtonMenuItem (
  3881:           modelGroup,
  3882:           specifiedModel == Model.SHODAI,
  3883:           "X68000 (10MHz)",
  3884:           listener),
  3885:         mdlACEMenuItem = ComponentFactory.createRadioButtonMenuItem (
  3886:           modelGroup,
  3887:           specifiedModel == Model.ACE,
  3888:           "X68000 ACE (10MHz)",
  3889:           listener),
  3890:         mdlEXPERTMenuItem = ComponentFactory.createRadioButtonMenuItem (
  3891:           modelGroup,
  3892:           specifiedModel == Model.EXPERT,
  3893:           "X68000 EXPERT (10MHz)",
  3894:           listener),
  3895:         mdlPROMenuItem = ComponentFactory.createRadioButtonMenuItem (
  3896:           modelGroup,
  3897:           specifiedModel == Model.PRO && specifiedAccelerator == 0,
  3898:           "X68000 PRO (10MHz)",
  3899:           listener),
  3900:         mdlSUPERMenuItem = ComponentFactory.createRadioButtonMenuItem (
  3901:           modelGroup,
  3902:           specifiedModel == Model.SUPER,
  3903:           "X68000 SUPER (10MHz)",
  3904:           listener),
  3905:         mdlXVIMenuItem = ComponentFactory.createRadioButtonMenuItem (
  3906:           modelGroup,
  3907:           specifiedModel == Model.XVI && specifiedAccelerator == 0,
  3908:           "X68000 XVI (16.7MHz)",
  3909:           listener),
  3910:         mdlCompactMenuItem = ComponentFactory.createRadioButtonMenuItem (
  3911:           modelGroup,
  3912:           specifiedModel == Model.COMPACT && specifiedAccelerator == 0,
  3913:           "X68000 Compact (16.7MHz)",
  3914:           listener),
  3915:         //
  3916:         ComponentFactory.createHorizontalSeparator (),
  3917:         //
  3918:         mdlX68030MenuItem = ComponentFactory.createRadioButtonMenuItem (
  3919:           modelGroup,
  3920:           specifiedModel == Model.X68030 && specifiedAccelerator == 0,
  3921:           "X68030 (25MHz)",
  3922:           listener),
  3923:         mdl030CompactMenuItem = ComponentFactory.createRadioButtonMenuItem (
  3924:           modelGroup,
  3925:           specifiedModel == Model.X68030COMPACT,
  3926:           "X68030 Compact (25MHz)",
  3927:           listener),
  3928:         //
  3929:         ComponentFactory.createHorizontalSeparator (),
  3930:         //
  3931:         mdlHybridMenuItem = ComponentFactory.createRadioButtonMenuItem (
  3932:           modelGroup,
  3933:           specifiedModel == Model.COMPACT && specifiedAccelerator == ACCELERATOR_HYBRID,
  3934:           "X68000 Hybrid (" + MHZ_HYBRID_STRING + "MHz)",
  3935:           listener),
  3936:         mdlXellent30MenuItem = ComponentFactory.createRadioButtonMenuItem (
  3937:           modelGroup,
  3938:           specifiedModel == Model.XVI && specifiedAccelerator == ACCELERATOR_XELLENT30,
  3939:           "Xellent30 (33.3MHz)",
  3940:           listener),
  3941:         mdl060turboMenuItem = ComponentFactory.createRadioButtonMenuItem (
  3942:           modelGroup,
  3943:           specifiedModel == Model.X68030 && specifiedAccelerator == ACCELERATOR_060TURBO,
  3944:           "060turbo (" + MHZ_060TURBO_STRING + "MHz)",
  3945:           listener),
  3946:         mdl060turboPROMenuItem = ComponentFactory.createRadioButtonMenuItem (
  3947:           modelGroup,
  3948:           specifiedModel == Model.PRO && specifiedAccelerator == ACCELERATOR_060TURBOPRO,
  3949:           "060turboPRO (" + MHZ_060TURBO_STRING + "MHz)",
  3950:           listener),
  3951:         //
  3952:         ComponentFactory.createHorizontalSeparator (),
  3953:         //
  3954:         mdlMC68010MenuItem = ComponentFactory.createCheckBoxMenuItem (
  3955:           specifiedMPU == Model.MPU_MC68010,
  3956:           "MC68010",
  3957:           listener)
  3958:         ),
  3959:       "ja", "機種を変更してリセット");
  3960: 
  3961:     ButtonGroup fpuGroup = new ButtonGroup ();
  3962:     fpuMenuItem0 = ComponentFactory.setEnabled (
  3963:       Multilingual.mlnText (
  3964:         ComponentFactory.createRadioButtonMenuItem (
  3965:           fpuGroup,
  3966:           specifiedFPU == 0,
  3967:           "No FPU",
  3968:           listener),
  3969:         "ja", "FPU なし"),
  3970:       Model.MPU_MC68020 <= specifiedFirstMPU ||
  3971:       Model.MPU_MC68020 <= specifiedSecondMPU);
  3972:     fpuMenuItem1 = ComponentFactory.setEnabled (
  3973:       Multilingual.mlnText (
  3974:         ComponentFactory.createRadioButtonMenuItem (
  3975:           fpuGroup,
  3976:           specifiedFPU != 0 && !specifiedTriplePrecision,
  3977:           "Extended precision (19 digit)",
  3978:           listener),
  3979:         "ja", "拡張精度 (19 桁)"),
  3980:       Model.MPU_MC68020 <= specifiedFirstMPU ||
  3981:       Model.MPU_MC68020 <= specifiedSecondMPU);
  3982:     fpuMenuItem2 = ComponentFactory.setEnabled (
  3983:       Multilingual.mlnText (
  3984:         ComponentFactory.createRadioButtonMenuItem (
  3985:           fpuGroup,
  3986:           specifiedFPU != 0 && specifiedTriplePrecision,
  3987:           "Triple precision (24 digit)",
  3988:           listener),
  3989:         "ja", "三倍精度 (24 桁)"),
  3990:       Model.MPU_MC68020 <= specifiedFirstMPU ||
  3991:       Model.MPU_MC68020 <= specifiedSecondMPU);
  3992:     fpuMenuItem3 = ComponentFactory.setEnabled (
  3993:       Multilingual.mlnText (
  3994:         ComponentFactory.createCheckBoxMenuItem (
  3995:           specifiedFullSpecification,
  3996:           "Full specification FPU",
  3997:           listener),
  3998:         "ja", "フルスペック FPU"),
  3999:       Model.MPU_MC68040 <= specifiedFirstMPU ||
  4000:       Model.MPU_MC68040 <= specifiedSecondMPU);
  4001: 
  4002:   }  //mdlMakeMenu
  4003: 
  4004:   public static void mdlRequestModel (Model model, int accelerator) {
  4005:     specifiedModel = model;
  4006:     specifiedAccelerator = accelerator;
  4007:     //MPU
  4008:     specifiedIsSecond = false;
  4009:     specifiedFirstMPU = specifiedModel.getMPU ();
  4010:     specifiedSecondMPU = Model.MPU_MC68EC030;
  4011:     specifiedMPU = specifiedIsSecond ? specifiedSecondMPU : specifiedFirstMPU;
  4012:     specifiedFirstClock = specifiedModel.getClock ();
  4013:     specifiedSecondClock = specifiedFirstClock * 2.0;
  4014:     specifiedClock = specifiedIsSecond ? specifiedSecondClock : specifiedFirstClock;
  4015:     //MC68010
  4016:     if (specifiedFirstMPU == Model.MPU_MC68000 &&
  4017:         mdlMC68010MenuItem.isSelected ()) {
  4018:       specifiedFirstMPU = Model.MPU_MC68010;
  4019:     }
  4020:     //アクセラレータ
  4021:     switch (accelerator) {
  4022:     case ACCELERATOR_HYBRID:
  4023:       specifiedFirstClock = MHZ_HYBRID_VALUE;  //33.3MHz
  4024:       specifiedClock = specifiedIsSecond ? specifiedSecondClock : specifiedFirstClock;
  4025:       break;
  4026:     case ACCELERATOR_XELLENT30:
  4027:       break;
  4028:     case ACCELERATOR_060TURBO:
  4029:     case ACCELERATOR_060TURBOPRO:
  4030:       specifiedFirstMPU = Model.MPU_MC68060;
  4031:       specifiedFirstClock = MHZ_060TURBO_VALUE;
  4032:       specifiedClock = specifiedIsSecond ? specifiedSecondClock : specifiedFirstClock;
  4033:     }
  4034:     //任意の負荷率と任意の周波数を無効化
  4035:     mpuUtilOn = false;
  4036:     mpuArbFreqOn = false;
  4037:     mpuSetCurrentClock (specifiedClock);
  4038:     //機種を変更してリセットのラジオボタンをセット
  4039:     if (accelerator == ACCELERATOR_HYBRID) {
  4040:       mdlHybridMenuItem.setSelected (true);
  4041:     } else if (accelerator == ACCELERATOR_XELLENT30) {
  4042:       mdlXellent30MenuItem.setSelected (true);
  4043:     } else if (accelerator == ACCELERATOR_060TURBO) {
  4044:       mdl060turboMenuItem.setSelected (true);
  4045:     } else if (accelerator == ACCELERATOR_060TURBOPRO) {
  4046:       mdl060turboPROMenuItem.setSelected (true);
  4047:     } else if (specifiedModel == Model.SHODAI) {
  4048:       mdlShodaiMenuItem.setSelected (true);
  4049:     } else if (specifiedModel == Model.ACE) {
  4050:       mdlACEMenuItem.setSelected (true);
  4051:     } else if (specifiedModel == Model.EXPERT) {
  4052:       mdlEXPERTMenuItem.setSelected (true);
  4053:     } else if (specifiedModel == Model.PRO) {
  4054:       mdlPROMenuItem.setSelected (true);
  4055:     } else if (specifiedModel == Model.SUPER) {
  4056:       mdlSUPERMenuItem.setSelected (true);
  4057:     } else if (specifiedModel == Model.XVI) {
  4058:       mdlXVIMenuItem.setSelected (true);
  4059:     } else if (specifiedModel == Model.COMPACT) {
  4060:       mdlCompactMenuItem.setSelected (true);
  4061:     } else if (specifiedModel == Model.X68030) {
  4062:       mdlX68030MenuItem.setSelected (true);
  4063:     } else if (specifiedModel == Model.X68030COMPACT) {
  4064:       mdl030CompactMenuItem.setSelected (true);
  4065:     }
  4066:     //FPU
  4067:     fpuMenuItem0.setEnabled (Model.MPU_MC68020 <= specifiedFirstMPU ||
  4068:                              Model.MPU_MC68020 <= specifiedSecondMPU);  //no fpu
  4069:     fpuMenuItem1.setEnabled (Model.MPU_MC68020 <= specifiedFirstMPU ||
  4070:                              Model.MPU_MC68020 <= specifiedSecondMPU);  //extended precision
  4071:     fpuMenuItem2.setEnabled (Model.MPU_MC68020 <= specifiedFirstMPU ||
  4072:                              Model.MPU_MC68020 <= specifiedSecondMPU);  //triple precision
  4073:     fpuMenuItem3.setEnabled (Model.MPU_MC68040 <= specifiedFirstMPU ||
  4074:                              Model.MPU_MC68040 <= specifiedSecondMPU);  //full specification
  4075:     //SCSI
  4076:     HDC.hdcSASIMenuItem.setSelected (!currentModel.isSCSI ());  //Built-in SASI
  4077:     SPC.spcSCSIINMenuItem.setSelected (currentModel.isSCSI ());  //Built-in SCSI
  4078:   }
  4079: 
  4080: 
  4081: 
  4082:   //========================================================================================
  4083:   //$$MPU MPU
  4084: 
  4085:   //コンパイルスイッチ
  4086:   public static final boolean MPU_INLINE_EXCEPTION = true;  //true=例外処理をインライン展開する。速くなる
  4087:   public static final boolean MPU_COMPOUND_POSTINCREMENT = false;  //true=(pc)+をbusRbs((pc+=2)-1),busRws((pc+=2)-2),busRls((pc+=4)-4)のように書く。見た目はスマートだが最適化しにくくなる?
  4088: 
  4089:   public static final boolean MPU_SWITCH_MISC_OPCODE = false;  //true=RTSなどのswitchのキーはオペコード全体,false=下位6bit
  4090:   public static final boolean MPU_SWITCH_BCC_CONDITION = false;  //true=オペコードのswitchでBccをccで分類する
  4091:   public static final boolean MPU_SWITCH_BCC_OFFSET = false;  //true=オペコードのswitchでBRA/BSR/Bccを8bitオフセットの上位2bitで分類する
  4092:   public static final boolean MPU_SWITCH_SCC_CONDITION = true;  //true=オペコードのswitchでScc/DBRA/DBcc/TRAPccをccで分類する
  4093: 
  4094:   public static final boolean MPU_OMIT_EXTRA_READ = false;  //true=余分なリードを省略する。MC68000のBRA.S/BSR.S/Bcc.S/CLR/SF
  4095:   public static final boolean MPU_OMIT_OFFSET_READ = false;  //true=条件分岐命令で分岐しないときオフセットのリードを省略する
  4096: 
  4097:   //TMR_FREQ単位のタイマカウンタで到達し得ない時刻を表す定数
  4098:   //  TMR_FREQ=10^12のとき到達するのに3.5ヶ月かかる
  4099:   //  3.5ヶ月間動かしっぱなしにすると破綻する
  4100:   public static final long FAR_FUTURE = 0x7fffffffffffffffL;
  4101: 
  4102:   //ステータスレジスタ
  4103:   //  トレース
  4104:   //     srT1    srT0
  4105:   //    0x0000  0x0000  トレースなし
  4106:   //    0x0000  0x4000  フローの変化をトレース
  4107:   //    0x8000  0x0000  すべての命令をトレース
  4108:   //    0x8000  0x4000  未定義
  4109:   public static final int REG_SR_T1  = 0b10000000_00000000;
  4110:   public static final int REG_SR_T0  = 0b01000000_00000000;  //(020/030/040)
  4111:   //  モード
  4112:   //      srS     srM
  4113:   //    0x0000  0x0000  ユーザモード(USPを使用)
  4114:   //    0x0000  0x1000  ユーザモード(USPを使用)
  4115:   //    0x2000  0x0000  スーパーバイザ割り込みモード(ISPを使用)
  4116:   //    0x2000  0x1000  スーパーバイザマスタモード(MSPを使用)
  4117:   public static final int REG_SR_S   = 0b00100000_00000000;
  4118:   public static final int REG_SR_M   = 0b00010000_00000000;  //(020/030/040/060)
  4119:   //  割り込み
  4120:   public static final int REG_SR_I   = 0b00000111_00000000;
  4121: 
  4122:   //コンディションコードレジスタ
  4123:   public static final int REG_CCR_X  = 0b00000000_00010000;
  4124:   public static final int REG_CCR_N  = 0b00000000_00001000;
  4125:   public static final int REG_CCR_Z  = 0b00000000_00000100;
  4126:   public static final int REG_CCR_V  = 0b00000000_00000010;
  4127:   public static final int REG_CCR_C  = 0b00000000_00000001;
  4128:   public static final int REG_CCR_MASK = REG_CCR_X | REG_CCR_N | REG_CCR_Z | REG_CCR_V | REG_CCR_C;  //CCRの有効なビット
  4129: 
  4130:   public static char[] REG_CCRXMAP = "00000000000000001111111111111111".toCharArray ();
  4131:   public static char[] REG_CCRNMAP = "00000000111111110000000011111111".toCharArray ();
  4132:   public static char[] REG_CCRZMAP = "00001111000011110000111100001111".toCharArray ();
  4133:   public static char[] REG_CCRVMAP = "00110011001100110011001100110011".toCharArray ();
  4134:   public static char[] REG_CCRCMAP = "01010101010101010101010101010101".toCharArray ();
  4135: 
  4136:   //割り込みレベル
  4137:   //  順序の変更やレベルの追加はコードの変更が必要
  4138:   public static final int MPU_IOI_INTERRUPT_LEVEL = 1;
  4139:   public static final int MPU_EB2_INTERRUPT_LEVEL = 2;
  4140:   public static final int MPU_DMA_INTERRUPT_LEVEL = 3;
  4141:   public static final int MPU_SCC_INTERRUPT_LEVEL = 5;
  4142:   public static final int MPU_MFP_INTERRUPT_LEVEL = 6;
  4143:   public static final int MPU_SYS_INTERRUPT_LEVEL = 7;
  4144:   public static final int MPU_IOI_INTERRUPT_MASK = 0x80 >> MPU_IOI_INTERRUPT_LEVEL;  //0x40
  4145:   public static final int MPU_EB2_INTERRUPT_MASK = 0x80 >> MPU_EB2_INTERRUPT_LEVEL;  //0x20
  4146:   public static final int MPU_DMA_INTERRUPT_MASK = 0x80 >> MPU_DMA_INTERRUPT_LEVEL;  //0x10
  4147:   public static final int MPU_SCC_INTERRUPT_MASK = 0x80 >> MPU_SCC_INTERRUPT_LEVEL;  //0x04
  4148:   public static final int MPU_MFP_INTERRUPT_MASK = 0x80 >> MPU_MFP_INTERRUPT_LEVEL;  //0x02
  4149:   public static final int MPU_SYS_INTERRUPT_MASK = 0x80 >> MPU_SYS_INTERRUPT_LEVEL;  //0x01
  4150: 
  4151:   public static final boolean MPU_INTERRUPT_SWITCH = true;  //true=最上位の割り込みをswitchで判別する
  4152: 
  4153:   //コンディションコード
  4154:   public static final boolean T = true;
  4155:   public static final boolean F = false;
  4156:   //  cccc==CCCC_cc                               cccc  cc
  4157:   public static final int CCCC_T  = 0b0000;  //0000  T       1                always true
  4158:   public static final int CCCC_F  = 0b0001;  //0001  F       0                always false
  4159:   public static final int CCCC_HI = 0b0010;  //0010  HI      ~C&~Z            high
  4160:   public static final int CCCC_LS = 0b0011;  //0011  LS      C|Z              low or same
  4161:   public static final int CCCC_CC = 0b0100;  //0100  CC(HS)  ~C               carry clear (high or same)
  4162:   public static final int CCCC_CS = 0b0101;  //0101  CS(LO)  C                carry set (low)
  4163:   public static final int CCCC_NE = 0b0110;  //0110  NE      ~Z               not equal
  4164:   public static final int CCCC_EQ = 0b0111;  //0111  EQ      Z                equal
  4165:   public static final int CCCC_VC = 0b1000;  //1000  VC      ~V               overflow clear
  4166:   public static final int CCCC_VS = 0b1001;  //1001  VS      V                overflow set
  4167:   public static final int CCCC_PL = 0b1010;  //1010  PL      ~N               plus
  4168:   public static final int CCCC_MI = 0b1011;  //1011  MI      N                minus
  4169:   public static final int CCCC_GE = 0b1100;  //1100  GE      N&V|~N&~V        greater or equal
  4170:   public static final int CCCC_LT = 0b1101;  //1101  LT      N&~V|~N&V        less than
  4171:   public static final int CCCC_GT = 0b1110;  //1110  GT      N&V&~Z|~N&~V&~Z  greater than
  4172:   public static final int CCCC_LE = 0b1111;  //1111  LE      Z|N&~V|~N&V      less or equal
  4173:   //F,F,F,F,F,F,F,F,F,F,F,F,F,F,F,F,T,T,T,T,T,T,T,T,T,T,T,T,T,T,T,T,  //X
  4174:   //F,F,F,F,F,F,F,F,T,T,T,T,T,T,T,T,F,F,F,F,F,F,F,F,T,T,T,T,T,T,T,T,  //N
  4175:   //F,F,F,F,T,T,T,T,F,F,F,F,T,T,T,T,F,F,F,F,T,T,T,T,F,F,F,F,T,T,T,T,  //Z
  4176:   //F,F,T,T,F,F,T,T,F,F,T,T,F,F,T,T,F,F,T,T,F,F,T,T,F,F,T,T,F,F,T,T,  //V
  4177:   //F,T,F,T,F,T,F,T,F,T,F,T,F,T,F,T,F,T,F,T,F,T,F,T,F,T,F,T,F,T,F,T,  //C
  4178:   //  BCCMAP[CCCC_cc<<5|ccr]==trueならば条件成立
  4179:   public static final boolean[] BCCMAP = {
  4180:     T,T,T,T,T,T,T,T,T,T,T,T,T,T,T,T,T,T,T,T,T,T,T,T,T,T,T,T,T,T,T,T,  //T       NF
  4181:     F,F,F,F,F,F,F,F,F,F,F,F,F,F,F,F,F,F,F,F,F,F,F,F,F,F,F,F,F,F,F,F,  //F       NT
  4182:     T,F,T,F,F,F,F,F,T,F,T,F,F,F,F,F,T,F,T,F,F,F,F,F,T,F,T,F,F,F,F,F,  //HI      NLS
  4183:     F,T,F,T,T,T,T,T,F,T,F,T,T,T,T,T,F,T,F,T,T,T,T,T,F,T,F,T,T,T,T,T,  //LS      NHI
  4184:     T,F,T,F,T,F,T,F,T,F,T,F,T,F,T,F,T,F,T,F,T,F,T,F,T,F,T,F,T,F,T,F,  //CC(HS)  NCS(NLO)
  4185:     F,T,F,T,F,T,F,T,F,T,F,T,F,T,F,T,F,T,F,T,F,T,F,T,F,T,F,T,F,T,F,T,  //CS(LO)  NCC(NHS)
  4186:     T,T,T,T,F,F,F,F,T,T,T,T,F,F,F,F,T,T,T,T,F,F,F,F,T,T,T,T,F,F,F,F,  //NE(NZ)  NEQ(NZE)
  4187:     F,F,F,F,T,T,T,T,F,F,F,F,T,T,T,T,F,F,F,F,T,T,T,T,F,F,F,F,T,T,T,T,  //EQ(ZE)  NNE(NNZ)
  4188:     T,T,F,F,T,T,F,F,T,T,F,F,T,T,F,F,T,T,F,F,T,T,F,F,T,T,F,F,T,T,F,F,  //VC      NVS
  4189:     F,F,T,T,F,F,T,T,F,F,T,T,F,F,T,T,F,F,T,T,F,F,T,T,F,F,T,T,F,F,T,T,  //VS      NVC
  4190:     T,T,T,T,T,T,T,T,F,F,F,F,F,F,F,F,T,T,T,T,T,T,T,T,F,F,F,F,F,F,F,F,  //PL      NMI
  4191:     F,F,F,F,F,F,F,F,T,T,T,T,T,T,T,T,F,F,F,F,F,F,F,F,T,T,T,T,T,T,T,T,  //MI      NPL
  4192:     T,T,F,F,T,T,F,F,F,F,T,T,F,F,T,T,T,T,F,F,T,T,F,F,F,F,T,T,F,F,T,T,  //GE      NLT
  4193:     F,F,T,T,F,F,T,T,T,T,F,F,T,T,F,F,F,F,T,T,F,F,T,T,T,T,F,F,T,T,F,F,  //LT      NGE
  4194:     T,T,F,F,F,F,F,F,F,F,T,T,F,F,F,F,T,T,F,F,F,F,F,F,F,F,T,T,F,F,F,F,  //GT      NLE
  4195:     F,F,T,T,T,T,T,T,T,T,F,F,T,T,T,T,F,F,T,T,T,T,T,T,T,T,F,F,T,T,T,T,  //LE      NGT
  4196:   };
  4197: 
  4198:   //  MPU_CCCMAP[cccc<<5|ccr]==(BCCMAP[cccc<<5|ccr]?'1':'0')
  4199:   public static final char[] MPU_CCCMAP = (
  4200:     "11111111111111111111111111111111" +
  4201:     "00000000000000000000000000000000" +
  4202:     "10100000101000001010000010100000" +
  4203:     "01011111010111110101111101011111" +
  4204:     "10101010101010101010101010101010" +
  4205:     "01010101010101010101010101010101" +
  4206:     "11110000111100001111000011110000" +
  4207:     "00001111000011110000111100001111" +
  4208:     "11001100110011001100110011001100" +
  4209:     "00110011001100110011001100110011" +
  4210:     "11111111000000001111111100000000" +
  4211:     "00000000111111110000000011111111" +
  4212:     "11001100001100111100110000110011" +
  4213:     "00110011110011000011001111001100" +
  4214:     "11000000001100001100000000110000" +
  4215:     "00111111110011110011111111001111").toCharArray ();
  4216: 
  4217:   //  (MPU_CC_cc<<ccr<0)==trueならば条件成立
  4218:   //  (MPU_CC_cc<<ccr<0)==BCCMAP[CCCC_cc<<5|ccr]
  4219:   public static final int MPU_CC_T  = 0b11111111111111111111111111111111;  //T
  4220:   public static final int MPU_CC_F  = 0b00000000000000000000000000000000;  //F
  4221:   public static final int MPU_CC_HI = 0b10100000101000001010000010100000;  //HI
  4222:   public static final int MPU_CC_LS = 0b01011111010111110101111101011111;  //LS
  4223:   public static final int MPU_CC_HS = 0b10101010101010101010101010101010;  //HS
  4224:   public static final int MPU_CC_LO = 0b01010101010101010101010101010101;  //LO
  4225:   public static final int MPU_CC_NE = 0b11110000111100001111000011110000;  //NE
  4226:   public static final int MPU_CC_EQ = 0b00001111000011110000111100001111;  //EQ
  4227:   public static final int MPU_CC_VC = 0b11001100110011001100110011001100;  //VC
  4228:   public static final int MPU_CC_VS = 0b00110011001100110011001100110011;  //VS
  4229:   public static final int MPU_CC_PL = 0b11111111000000001111111100000000;  //PL
  4230:   public static final int MPU_CC_MI = 0b00000000111111110000000011111111;  //MI
  4231:   public static final int MPU_CC_GE = 0b11001100001100111100110000110011;  //GE
  4232:   public static final int MPU_CC_LT = 0b00110011110011000011001111001100;  //LT
  4233:   public static final int MPU_CC_GT = 0b11000000001100001100000000110000;  //GT
  4234:   public static final int MPU_CC_LE = 0b00111111110011110011111111001111;  //LE
  4235: 
  4236:   //TST.Bのテーブル
  4237:   //  z=255&(~);ccr=ccr&CCR_X|MPU_TSTB_TABLE[z]をz=~;ccr=ccr&CCR_X|MPU_TSTB_TABLE[255&z]にすると速くなることがある
  4238:   //  インデックスが明示的にマスクされていると最適化しやすいのだろう
  4239: /*
  4240:   public static final byte[] MPU_TSTB_TABLE = new byte[256];
  4241:   static {
  4242:     for (int z = 0; z < 256; z++) {
  4243:       MPU_TSTB_TABLE[z] = (byte) (z >> 7 << 3 | z - 1 >> 6 & CCR_Z);
  4244:     }
  4245:   }  //static
  4246: */
  4247: /*
  4248:   public static final byte[] MPU_TSTB_TABLE = {
  4249:     REG_CCR_Z, 0,         0,         0,         0,         0,         0,         0,
  4250:     0,         0,         0,         0,         0,         0,         0,         0,
  4251:     0,         0,         0,         0,         0,         0,         0,         0,
  4252:     0,         0,         0,         0,         0,         0,         0,         0,
  4253:     0,         0,         0,         0,         0,         0,         0,         0,
  4254:     0,         0,         0,         0,         0,         0,         0,         0,
  4255:     0,         0,         0,         0,         0,         0,         0,         0,
  4256:     0,         0,         0,         0,         0,         0,         0,         0,
  4257:     0,         0,         0,         0,         0,         0,         0,         0,
  4258:     0,         0,         0,         0,         0,         0,         0,         0,
  4259:     0,         0,         0,         0,         0,         0,         0,         0,
  4260:     0,         0,         0,         0,         0,         0,         0,         0,
  4261:     0,         0,         0,         0,         0,         0,         0,         0,
  4262:     0,         0,         0,         0,         0,         0,         0,         0,
  4263:     0,         0,         0,         0,         0,         0,         0,         0,
  4264:     0,         0,         0,         0,         0,         0,         0,         0,
  4265:     REG_CCR_N, REG_CCR_N, REG_CCR_N, REG_CCR_N, REG_CCR_N, REG_CCR_N, REG_CCR_N, REG_CCR_N,
  4266:     REG_CCR_N, REG_CCR_N, REG_CCR_N, REG_CCR_N, REG_CCR_N, REG_CCR_N, REG_CCR_N, REG_CCR_N,
  4267:     REG_CCR_N, REG_CCR_N, REG_CCR_N, REG_CCR_N, REG_CCR_N, REG_CCR_N, REG_CCR_N, REG_CCR_N,
  4268:     REG_CCR_N, REG_CCR_N, REG_CCR_N, REG_CCR_N, REG_CCR_N, REG_CCR_N, REG_CCR_N, REG_CCR_N,
  4269:     REG_CCR_N, REG_CCR_N, REG_CCR_N, REG_CCR_N, REG_CCR_N, REG_CCR_N, REG_CCR_N, REG_CCR_N,
  4270:     REG_CCR_N, REG_CCR_N, REG_CCR_N, REG_CCR_N, REG_CCR_N, REG_CCR_N, REG_CCR_N, REG_CCR_N,
  4271:     REG_CCR_N, REG_CCR_N, REG_CCR_N, REG_CCR_N, REG_CCR_N, REG_CCR_N, REG_CCR_N, REG_CCR_N,
  4272:     REG_CCR_N, REG_CCR_N, REG_CCR_N, REG_CCR_N, REG_CCR_N, REG_CCR_N, REG_CCR_N, REG_CCR_N,
  4273:     REG_CCR_N, REG_CCR_N, REG_CCR_N, REG_CCR_N, REG_CCR_N, REG_CCR_N, REG_CCR_N, REG_CCR_N,
  4274:     REG_CCR_N, REG_CCR_N, REG_CCR_N, REG_CCR_N, REG_CCR_N, REG_CCR_N, REG_CCR_N, REG_CCR_N,
  4275:     REG_CCR_N, REG_CCR_N, REG_CCR_N, REG_CCR_N, REG_CCR_N, REG_CCR_N, REG_CCR_N, REG_CCR_N,
  4276:     REG_CCR_N, REG_CCR_N, REG_CCR_N, REG_CCR_N, REG_CCR_N, REG_CCR_N, REG_CCR_N, REG_CCR_N,
  4277:     REG_CCR_N, REG_CCR_N, REG_CCR_N, REG_CCR_N, REG_CCR_N, REG_CCR_N, REG_CCR_N, REG_CCR_N,
  4278:     REG_CCR_N, REG_CCR_N, REG_CCR_N, REG_CCR_N, REG_CCR_N, REG_CCR_N, REG_CCR_N, REG_CCR_N,
  4279:     REG_CCR_N, REG_CCR_N, REG_CCR_N, REG_CCR_N, REG_CCR_N, REG_CCR_N, REG_CCR_N, REG_CCR_N,
  4280:     REG_CCR_N, REG_CCR_N, REG_CCR_N, REG_CCR_N, REG_CCR_N, REG_CCR_N, REG_CCR_N, REG_CCR_N,
  4281:   };
  4282: */
  4283:   //  perl misc/itob.pl xeij/XEiJ.java MPU_TSTB_TABLE
  4284:   public static final byte[] MPU_TSTB_TABLE = "\4\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b".getBytes (XEiJ.ISO_8859_1);
  4285: 
  4286:   //BITREVのテーブル
  4287:   //  初期化コードが大きくなりすぎるので最初から展開しておくにはクラスを分ける必要がある
  4288:   public static final int[] MPU_BITREV_TABLE_0 = new int[2048];
  4289:   public static final int[] MPU_BITREV_TABLE_1 = new int[2048];
  4290:   public static final int[] MPU_BITREV_TABLE_2 = new int[2048];
  4291:   static {
  4292:     for (int i = 0; i < 2048; i++) {
  4293:       MPU_BITREV_TABLE_2[i] = (MPU_BITREV_TABLE_1[i] = (MPU_BITREV_TABLE_0[i] = Integer.reverse (i)) >>> 11) >>> 11;
  4294:     }
  4295:   }
  4296: 
  4297:   //アドレッシングモード
  4298:   //                                                              data  memory  control  alterable
  4299:   public static final int EA_DR = 0b000_000;  //D  Dr             x                      x
  4300:   public static final int EA_AR = 0b001_000;  //A  Ar                                    x
  4301:   public static final int EA_MM = 0b010_000;  //M  (Ar)           x     x       x        x
  4302:   public static final int EA_MP = 0b011_000;  //+  (Ar)+          x     x                x
  4303:   public static final int EA_MN = 0b100_000;  //-  -(Ar)          x     x                x
  4304:   public static final int EA_MW = 0b101_000;  //W  (d16,Ar)       x     x       x        x
  4305:   public static final int EA_MX = 0b110_000;  //X  (d8,Ar,Rn.wl)  x     x       x        x
  4306:   public static final int EA_ZW = 0b111_000;  //Z  (xxx).W        x     x       x        x
  4307:   public static final int EA_ZL = 0b111_001;  //Z  (xxx).L        x     x       x        x
  4308:   public static final int EA_PW = 0b111_010;  //P  (d16,PC)       x     x       x
  4309:   public static final int EA_PX = 0b111_011;  //P  (d8,PC,Rn.wl)  x     x       x
  4310:   public static final int EA_IM = 0b111_100;  //I  #<data>        x
  4311:   public static final int MMM_DR = EA_DR >> 3;
  4312:   public static final int MMM_AR = EA_AR >> 3;
  4313:   public static final int MMM_MM = EA_MM >> 3;
  4314:   public static final int MMM_MP = EA_MP >> 3;
  4315:   public static final int MMM_MN = EA_MN >> 3;
  4316:   public static final int MMM_MW = EA_MW >> 3;
  4317:   public static final int MMM_MX = EA_MX >> 3;
  4318:   public static final long EAM_DR = 0xff00000000000000L >>> EA_DR;
  4319:   public static final long EAM_AR = 0xff00000000000000L >>> EA_AR;
  4320:   public static final long EAM_MM = 0xff00000000000000L >>> EA_MM;
  4321:   public static final long EAM_MP = 0xff00000000000000L >>> EA_MP;
  4322:   public static final long EAM_MN = 0xff00000000000000L >>> EA_MN;
  4323:   public static final long EAM_MW = 0xff00000000000000L >>> EA_MW;
  4324:   public static final long EAM_MX = 0xff00000000000000L >>> EA_MX;
  4325:   public static final long EAM_ZW = 0x8000000000000000L >>> EA_ZW;
  4326:   public static final long EAM_ZL = 0x8000000000000000L >>> EA_ZL;
  4327:   public static final long EAM_PW = 0x8000000000000000L >>> EA_PW;
  4328:   public static final long EAM_PX = 0x8000000000000000L >>> EA_PX;
  4329:   public static final long EAM_IM = 0x8000000000000000L >>> EA_IM;
  4330:   public static final long EAM_ALL = EAM_DR|EAM_AR|EAM_MM|EAM_MP|EAM_MN|EAM_MW|EAM_MX|EAM_ZW|EAM_ZL|EAM_PW|EAM_PX|EAM_IM;  //|DAM+-WXZPI|すべて
  4331:   public static final long EAM_ALT = EAM_DR|EAM_AR|EAM_MM|EAM_MP|EAM_MN|EAM_MW|EAM_MX|EAM_ZW|EAM_ZL                     ;  //|DAM+-WXZ  |可変
  4332:   public static final long EAM_DAT = EAM_DR       |EAM_MM|EAM_MP|EAM_MN|EAM_MW|EAM_MX|EAM_ZW|EAM_ZL|EAM_PW|EAM_PX|EAM_IM;  //|D M+-WXZPI|データ
  4333:   public static final long EAM_DME = EAM_DR       |EAM_MM|EAM_MP|EAM_MN|EAM_MW|EAM_MX|EAM_ZW|EAM_ZL|EAM_PW|EAM_PX       ;  //|D M+-WXZP |データレジスタ直接またはメモリ
  4334:   public static final long EAM_DLT = EAM_DR       |EAM_MM|EAM_MP|EAM_MN|EAM_MW|EAM_MX|EAM_ZW|EAM_ZL                     ;  //|D M+-WXZ  |データ可変
  4335:   public static final long EAM_DCN = EAM_DR       |EAM_MM              |EAM_MW|EAM_MX|EAM_ZW|EAM_ZL|EAM_PW|EAM_PX       ;  //|D M  WXZP |データレジスタ直接または制御
  4336:   public static final long EAM_DCL = EAM_DR       |EAM_MM              |EAM_MW|EAM_MX|EAM_ZW|EAM_ZL                     ;  //|D M  WXZ  |データレジスタ直接または制御可変
  4337:   public static final long EAM_ANY =               EAM_MM|EAM_MP|EAM_MN|EAM_MW|EAM_MX|EAM_ZW|EAM_ZL|EAM_PW|EAM_PX|EAM_IM;  //|  M+-WXZPI|レジスタ以外
  4338:   public static final long EAM_MEM =               EAM_MM|EAM_MP|EAM_MN|EAM_MW|EAM_MX|EAM_ZW|EAM_ZL|EAM_PW|EAM_PX       ;  //|  M+-WXZP |メモリ
  4339:   public static final long EAM_MLT =               EAM_MM|EAM_MP|EAM_MN|EAM_MW|EAM_MX|EAM_ZW|EAM_ZL                     ;  //|  M+-WXZ  |メモリ可変
  4340:   public static final long EAM_RDL =               EAM_MM|EAM_MP       |EAM_MW|EAM_MX|EAM_ZW|EAM_ZL|EAM_PW|EAM_PX       ;  //|  M+ WXZP |リードリスト
  4341:   public static final long EAM_WTL =               EAM_MM       |EAM_MN|EAM_MW|EAM_MX|EAM_ZW|EAM_ZL                     ;  //|  M -WXZ  |ライトリスト
  4342:   public static final long EAM_CNT =               EAM_MM              |EAM_MW|EAM_MX|EAM_ZW|EAM_ZL|EAM_PW|EAM_PX       ;  //|  M  WXZP |制御
  4343:   public static final long EAM_CLT =               EAM_MM              |EAM_MW|EAM_MX|EAM_ZW|EAM_ZL                     ;  //|  M  WXZ  |制御可変
  4344: 
  4345:   //汎用レジスタ
  4346:   //  r[15]は現在のスタックポインタ
  4347:   //                              ユーザモード      スーパーバイザモード
  4348:   //                                            マスタモード  割り込みモード
  4349:   //     ユーザスタックポインタ     regRn[15]       mpuUSP         mpuUSP
  4350:   //     マスタスタックポインタ      mpuMSP       regRn[15]        mpuMSP
  4351:   //    割り込みスタックポインタ     mpuISP        mpuISP        regRn[15]
  4352:   //  モードによってmpuUSP,mpuMSP,mpuISPのいずれかをregRn[15]にコピーして使う
  4353:   //  他のモードに切り替えるときはregRn[15]をコピー元のmpuUSP,mpuMSP,mpuISPのいずれかに書き戻してから切り替える
  4354:   //  例えばユーザモードから割り込みモードへ移行するときはregRn[15]→mpuUSP,mpuISP→regRn[15]とする
  4355:   public static final int[] regRn = new int[16 + 1];  //汎用レジスタ。regRn[16]はテンポラリ。レジスタの更新を回避するとき条件分岐する代わりにregRn[16]に書き込む
  4356: 
  4357:   //プログラムカウンタ
  4358:   public static int regPC;  //プログラムカウンタ
  4359:   public static int regPC0;  //実行中の命令の先頭アドレス
  4360: 
  4361:   //オペコードレジスタ
  4362:   public static int regOC;  //オペコード。16bit、0拡張
  4363: 
  4364:   //ステータスレジスタ
  4365:   public static int regSRT1;  //ステータスレジスタのT1。0=トレースなし,REG_SR_T1=すべての命令をトレース
  4366:   public static int regSRT0;  //ステータスレジスタのT0(020/030/040)。0=トレースなし,REG_SR_T0=フローの変化をトレース
  4367:   public static int mpuTraceFlag;  //トレースフラグ。命令実行前にregSRT1をコピーし、分岐命令を実行するときregSRT0をorする。例外が発生したとき0にする。命令実行後に0でなければトレース例外を発動する
  4368:   public static int regSRS;  //ステータスレジスタのS。0=ユーザモード,REG_SR_S=スーパーバイザモード
  4369:   public static int regSRM;  //ステータスレジスタのM(020/030/040/060)。0=割り込みモード,REG_SR_M=マスタモード。割り込みを開始するときクリアされる
  4370:   public static int regSRI;  //ステータスレジスタのI2,I1,I0
  4371: 
  4372:   //コンディションコードレジスタ
  4373:   public static int regCCR;  //コンディションコードレジスタ。000XNZVC。0のビットは0に固定
  4374: 
  4375:   //mpuIMR
  4376:   //  インタラプトマスクレジスタ
  4377:   //  ビットの並び順は01234567
  4378:   //  現在の割り込みマスクレベルよりも高いビットをセットしたマスク
  4379:   //    割り込みマスクレベルがnのときレベル1..nの割り込みが禁止されてレベルn+1..7の割り込みが許可される
  4380:   //    ただし、割り込みマスクレベルが7のときはレベル7割り込みの処理中でなければレベル7割り込みが許可される
  4381:   //  mpuIMR&mpuIRRで最下位の1のビットの割り込みを受け付ける
  4382:   //  irpSetSRでmpuIMR&mpuISRで1のビットの割り込みを終了する
  4383:   //  mpuIMR=0x7f>>(srI>>8)|~mpuISR&1
  4384:   //      srI     mpuIMR    受け付ける割り込みのレベルと順序
  4385:   //    0x0700  0b00000000  なし  レベル7割り込みの処理中のとき
  4386:   //            0b00000001  7     レベル7割り込みの処理中ではないとき
  4387:   //    0x0600  0b00000001  7
  4388:   //    0x0500  0b00000011  7 6
  4389:   //    0x0400  0b00000111  7 6 5
  4390:   //    0x0300  0b00001111  7 6 5 4
  4391:   //    0x0200  0b00011111  7 6 5 4 3
  4392:   //    0x0100  0b00111111  7 6 5 4 3 2
  4393:   //    0x0000  0b01111111  7 6 5 4 3 2 1
  4394:   public static int mpuIMR;
  4395: 
  4396:   //mpuIRR
  4397:   //  インタラプトリクエストレジスタ
  4398:   //  ビットの並び順は01234567
  4399:   //  デバイスが割り込みを要求するときレベルに対応するビットをセットする
  4400:   //  コアが割り込みを受け付けるときレベルに対応するビットをクリアしてデバイスのacknowledge()を呼び出す
  4401:   public static int mpuIRR;
  4402:   public static int mpuDIRR;  //遅延割り込み要求
  4403: 
  4404:   //mpuISR
  4405:   //  インタラプトインサービスレジスタ
  4406:   //  ビットの並び順は01234567
  4407:   //  コアが割り込み処理を開始するときレベルに対応するビットをセットする
  4408:   //  割り込みマスクレベルが下がったとき新しいレベルよりも高いレベルの割り込み処理が終了したものとみなし、
  4409:   //  レベルに対応するビットをクリアしてデバイスのdone()を呼び出す
  4410:   //  done()が呼び出された時点でまだ処理されていない割り込みが残っているデバイスは再度割り込みを要求する
  4411:   public static int mpuISR;
  4412: 
  4413:   //制御レジスタ
  4414:   public static int mpuSFC;    //000  -12346  SFC
  4415:   public static int mpuDFC;    //001  -12346  DFC
  4416:   public static int mpuCACR;   //002  --2346  CACR
  4417:   //protected static int mpuTC;     //003  ----46  TC                        030MMUのTC
  4418:   //protected static int mpuITT0;   //004  ----46  ITT0   IACR0 @ MC68EC040  030MMUのTT0
  4419:   //protected static int mpuITT1;   //005  ----46  ITT1   IACR1 @ MC68EC040  030MMUのTT1
  4420:   //protected static int mpuDTT0;   //006  ----46  DTT0   DACR0 @ MC68EC040
  4421:   //protected static int mpuDTT1;   //007  ----46  DTT1   DACR1 @ MC68EC040
  4422:   public static int mpuBUSCR;  //008  -----6  BUSCR
  4423:   public static int mpuUSP;    //800  -12346  USP    隠れたユーザスタックポインタ。ユーザモードのときはr[15]を参照すること
  4424:   public static int mpuVBR;    //801  -12346  VBR    ベクタベースレジスタ
  4425:   public static int mpuCAAR;   //802  --23--  CAAR
  4426:   public static int mpuMSP;    //803  --234-  MSP    隠れたマスタスタックポインタ。マスタモードのときはr[15]を参照すること
  4427:   public static int mpuISP;    //804  --234-  ISP    隠れた割り込みスタックポインタ。割り込みモードのときはr[15]を参照すること
  4428:   //protected static int mpuMMUSR;  //805  ----4-  MMUSR                     030MMUのMMUSR
  4429:   //protected static int mpuURP;    //806  ----46  URP                       030MMUのCRPの下位32bit
  4430:   //protected static int mpuSRP;    //807  ----46  SRP                       030MMUのSRPの下位32bit
  4431:   public static int mpuPCR;    //808  -----6  PCR
  4432:   //protected static int mpuHCRP;   //                                       030MMUのCRPの上位32bit
  4433:   //protected static int mpuHSRP;   //                                       030MMUのSRPの上位32bit
  4434: 
  4435:   public static final int MPU_060_REV = 7;  //MC68060のリビジョンナンバー。1=F43G,5=G65V,6=E41J
  4436: 
  4437:   //クロック
  4438:   //  時刻は開始からの経過時間
  4439:   public static long mpuClockTime;  //時刻(TMR_FREQ単位)
  4440:   public static long mpuClockLimit;  //タスクの終了時刻
  4441:   public static double mpuClockMHz;  //動作周波数の設定値(MHz)
  4442:   public static double mpuCurrentMHz;  //動作周波数の現在値(MHz)
  4443:   public static int mpuCycleCount;  //命令のサイクル数。実行アドレス計算のサイクル数を含む
  4444:   public static long mpuCycleUnit;  //周波数の表示に使用する1サイクルあたりの時間(TMR_FREQ単位)
  4445:   public static long mpuModifiedUnit;  //mpuCycleCountの1サイクルあたりの時間(TMR_FREQ単位)。MC68030のときmpuCycleUnit*3/5
  4446:   public static long dmaCycleUnit;  //DMAの1サイクルの時間(TMR_FREQ単位)
  4447: 
  4448:   //タイマ
  4449:   //  mpuTaskはコアをスケジュールしなおすときに毎回作り直す
  4450:   public static TimerTask mpuTask;  //null=停止中。null以外=動作中
  4451: 
  4452:   //その他
  4453:   public static int mpuBootDevice;  //起動デバイス。-1=指定なし
  4454:   public static int mpuROMBootHandle;  //ROM起動ハンドル。-1=指定なし
  4455:   public static int mpuSavedBootDevice;  //保存されている起動デバイス。-1=保存されていない
  4456:   public static int mpuSavedROMBootHandle;  //保存されているROM起動ハンドル。-1=保存されていない
  4457: 
  4458:   //コア
  4459:   public static boolean mpuIgnoreAddressError;  //true=アドレスエラーを無視する
  4460: 
  4461:   //ウェイトサイクル
  4462:   public static int mpuROMWaitCycles;  //MPUからROMにアクセスしたときのウェイトのサイクル数。X68000は1。X68030は$00E8E009の上位4bit+2
  4463:   public static int mpuRAMWaitCycles;  //MPUからRAMにアクセスしたときのウェイトのサイクル数。X68000は0。X68030は$00E8E009の下位4bit+2ただし0は0
  4464:   public static boolean mpuCacheOn;  //true=キャッシュON。MPUからRAMとROMにアクセスしたときのウェイトを0にすることで擬似的にキャッシュが効いているように見せる
  4465:   public static final class WaitTime {
  4466:     public long ram;
  4467:     public long gvram;
  4468:     public long tvram;
  4469:     public long crtc;
  4470:     public long palet;
  4471:     public long vicon;
  4472:     public long dmac;
  4473:     public long mfp;
  4474:     public long rtc;
  4475:     public long prnport;
  4476:     public long sysport;
  4477:     public long opm;
  4478:     public long adpcm;
  4479:     public long fdc;
  4480:     public long fdd;
  4481:     public long hdc;
  4482:     public long scc;
  4483:     public long ppi;
  4484:     public long ioi;
  4485:     public long sprc;
  4486:     public long sram;
  4487:     public long rom;
  4488:     public long ramlong;
  4489:     public long romlong;
  4490:   }
  4491:   public static final WaitTime mpuNoWaitTime = new WaitTime ();  //MPUウェイトなし
  4492:   public static final WaitTime dmaNoWaitTime = new WaitTime ();  //DMACウェイトなし
  4493:   public static final WaitTime mpuWaitTime = new WaitTime ();  //現在のMPUのウェイト
  4494:   public static final WaitTime dmaWaitTime = new WaitTime ();  //現在のDMACのウェイト
  4495:   public static boolean busWaitCyclesRequest;
  4496:   public static boolean busWaitCycles;  //true=ウェイトサイクルなし。mpuNoWaitTime/dmaNoWaitTimeを使う,false=ウェイトあり。mpuWaitTime/dmaWaitTimeを使う
  4497:   public static WaitTime busWaitTime;  //busWaitCycles?mpuWaitTime:mpuNoWaitTimeまたはbusWaitCycles?dmaWaitTime:dmaNoWaitTime
  4498: 
  4499:   //任意の周波数の指定
  4500:   public static boolean mpuArbFreqOn;  //true=任意の周波数の指定がある。mpuArbFreqOn&&mpuUtilOnは不可
  4501:   public static int mpuArbFreqMHz;  //任意の周波数の指定(MHz)。1~1000
  4502:   public static SpinnerNumberModel mpuArbFreqModel;
  4503:   public static JSpinner mpuArbFreqSpinner;
  4504:   public static JRadioButtonMenuItem mpuArbFreqRadioButtonMenuItem;
  4505: 
  4506:   //任意の負荷率の指定
  4507:   public static boolean mpuUtilOn;  //true=任意の負荷率の指定がある。mpuArbFreqOn&&mpuUtilOnは不可
  4508:   public static int mpuUtilRatio;  //任意の負荷率の指定(%)。1~100
  4509:   public static SpinnerNumberModel mpuUtilModel;
  4510:   public static JSpinner mpuUtilSpinner;
  4511:   public static JRadioButtonMenuItem mpuUtilRadioButtonMenuItem;
  4512: 
  4513:   //周波数と負荷率の調整
  4514:   public static final int MPU_ADJUSTMENT_INTERVAL = 100;  //間隔。TMR_INTERVAL*MPU_ADJUSTMENT_INTERVAL毎に表示する
  4515:   public static int mpuAdjustmentCounter;
  4516:   public static long mpuTotalNano;  //コアのスレッドの動作時間(ns)。本来の動作時間の1/10ならば負荷率10%
  4517:   public static long mpuLastNano;  //前回の時刻(ns)
  4518:   public static double mpuCoreNano1;
  4519:   public static double mpuCoreNano2;
  4520: 
  4521:   //メニュー
  4522:   public static JMenu mpuMenu;
  4523:   public static JMenuItem mpuResetMenuItem;
  4524:   public static JMenuItem mpuOpt1ResetMenuItem;
  4525:   public static JRadioButtonMenuItem mpuClock10MenuItem;
  4526:   public static JRadioButtonMenuItem mpuClock16MenuItem;
  4527:   public static JRadioButtonMenuItem mpuClock25MenuItem;
  4528:   public static JRadioButtonMenuItem mpuClock33MenuItem;
  4529:   public static JRadioButtonMenuItem mpuClock50MenuItem;
  4530:   public static JRadioButtonMenuItem mpuClock66MenuItem;
  4531:   public static JRadioButtonMenuItem mpuClock75MenuItem;
  4532:   public static JRadioButtonMenuItem mpuClock100MenuItem;
  4533: 
  4534:   //デバッグ
  4535:   public static ActionListener mpuDebugActionListener;  //デバッグアクションリスナー
  4536:   public static ArrayList<AbstractButton> mpuButtonsRunning;  //MPUが動作中のときだけ有効なボタン
  4537:   public static ArrayList<AbstractButton> mpuButtonsStopped;  //MPUが停止中のときだけ有効なボタン
  4538:   public static ArrayList<JCheckBox> mpuOriIllegalCheckBoxList;  //ORI.B #$00,D0を不当命令とみなすチェックボックスのリスト
  4539:   public static ArrayList<JCheckBox> mpuStopOnErrorCheckBoxList;  //エラーで停止するチェックボックスのリスト
  4540:   public static ArrayList<JCheckBox> mpuStopAtStartCheckBoxList;  //実行開始位置で停止するチェックボックスのリスト
  4541: 
  4542:   public static int mpuAdvanceCount;  //トレース実行のカウンタ。0以外=トレース実行中
  4543:   public static int mpuStepCount;  //ステップ実行のカウンタ。1以上=ステップ実行中。-1=ステップアンティルリターン実行中
  4544:   public static boolean mpuContinue;  //自然に終了したときは変化しない。インスタント命令ブレークポイントで停止したときはtrue、それ以外で停止したときはfalse
  4545:   public static int mpuUntilReturnSRS;  //ステップアンティルリターン開始時のregSRS
  4546:   public static int mpuUntilReturnRP;  //ステップアンティルリターン開始時のmmuSRPまたはmmuURP
  4547:   public static int mpuUntilReturnPC0;  //ステップアンティルリターン開始時のregPC0
  4548:   public static int mpuUntilReturnSP;  //ステップアンティルリターン開始時のregRn[15]
  4549: 
  4550:   //SX-Window ver3.1のバグ対策
  4551:   //
  4552:   //  無償公開されたSXWIN311.XDFから起動したときリソースファイルから読み込まれるコードに問題がある
  4553:   //  マウスカーソルが指しているメニューの項目の番号を返すサブルーチンでd1レジスタの上位ワードが不定のままdivu.w #$0010,d1を実行している
  4554:   //  このサブルーチンの引数ではないd1レジスタの上位ワードを0にしてから呼び出さないとメニューを選択できない
  4555:   //  実機で露見しないのは直前に呼び出されるサブルーチンが使っているmovem.w <ea>,<list>命令がd1レジスタの上位ワードをほぼ0にしているため
  4556:   //  XEiJで露見したのはこの命令の処理が間違っていてd1レジスタが符号拡張されず上位ワードが0になっていなかったため
  4557:   //
  4558:   //  問題のサブルーチン
  4559:   //    00BFCC74  48E77000              movem.l d1-d3,-(sp)                 H輛.
  4560:   //    00BFCC78  2600                  move.l  d0,d3                       &.
  4561:   //    00BFCC7A  2F00                  move.l  d0,-(sp)                    /.
  4562:   //    00BFCC7C  486DFF80              pea.l   $FF80(a5)                   Hm..
  4563:   //    00BFCC80  A156                  SXCALL  __GMPtInRect                。V
  4564:   //    00BFCC82  508F                  addq.l  #$08,sp                     P夙
  4565:   //    00BFCC84  6738                  beq.s   $00BFCCBE                   g8
  4566:   //    00BFCC86  2003                  move.l  d3,d0                        .
  4567:   //    00BFCC88  3200                  move.w  d0,d1                       2.
  4568:   //    00BFCC8A  4840                  swap.w  d0                          H@
  4569:   //    00BFCC8C  906DFF80              sub.w   $FF80(a5),d0                仁..
  4570:   //    00BFCC90  6B2C                  bmi.s   $00BFCCBE                   k,
  4571:   //    00BFCC92  B06DFF92              cmp.w   $FF92(a5),d0                ーm.地
  4572:   //    00BFCC96  6E26                  bgt.s   $00BFCCBE                   n&
  4573:   //    00BFCC98  926DFF82              sub.w   $FF82(a5),d1                知.L
  4574:   //    00BFCC9C  6B20                  bmi.s   $00BFCCBE                   k 
  4575:   //    00BFCC9E  342DFF9C              move.w  $FF9C(a5),d2                4-.愼
  4576:   //    00BFCCA2  C4FC0010              mulu.w  #$0010,d2                   ト...
  4577:   //    00BFCCA6  B242                  cmp.w   d2,d1                       イB
  4578:   //    00BFCCA8  6E14                  bgt.s   $00BFCCBE                   n.
  4579:   //    00BFCCAA  82FC0010              divu.w  #$0010,d1                   ※..    ←d1レジスタの上位ワードが不定のままdivu.wを実行している
  4580:   //    00BFCCAE  3001                  move.w  d1,d0                       0.
  4581:   //    00BFCCB0  4841                  swap.w  d1                          HA
  4582:   //    00BFCCB2  4A41                  tst.w   d1                          JA
  4583:   //    00BFCCB4  6702                  beq.s   $00BFCCB8                   g.
  4584:   //    00BFCCB6  5240                  addq.w  #$01,d0                     R@
  4585:   //    00BFCCB8  4CDF000E              movem.l (sp)+,d1-d3                 L゚..
  4586:   //    00BFCCBC  4E75                  rts                                 Nu
  4587:   //    00BFCCBE  7000                  moveq.l #$00,d0                     p.
  4588:   //    00BFCCC0  60F6                  bra.s   $00BFCCB8                   `.
  4589:   //
  4590:   //  問題のサブルーチンの呼び出し元
  4591:   //    00BFC9D6  4E56FFF0              link.w  a6,#$FFF0                   NV..
  4592:   //    00BFC9DA  6100FEF4              bsr.w   $00BFC8D0                   a...    ←直前に呼び出されるサブルーチン
  4593:   //    00BFC9DE  202C000A              move.l  $000A(a4),d0                 ,..
  4594:   //    00BFC9E2  61000290              bsr.w   $00BFCC74                   a...    ←問題のサブルーチン
  4595:   //    00BFC9E6  3200                  move.w  d0,d1                       2.
  4596:   //    00BFC9E8  3600                  move.w  d0,d3                       6.
  4597:   //    (以下略)
  4598:   //
  4599:   //  直前に呼び出されるサブルーチン
  4600:   //    00BFC8D0  426DFFA2              clr.w   $FFA2(a5)                   Bm.「
  4601:   //    00BFC8D4  206C0006              movea.l $0006(a4),a0                 l..
  4602:   //    00BFC8D8  4C90000F              movem.w (a0),d0-d3                  L...
  4603:   //    00BFC8DC  5240                  addq.w  #$01,d0                     R@
  4604:   //    00BFC8DE  5241                  addq.w  #$01,d1                     RA
  4605:   //    00BFC8E0  5342                  subq.w  #$01,d2                     SB
  4606:   //    00BFC8E2  5343                  subq.w  #$01,d3                     SC
  4607:   //    00BFC8E4  48AD000FFF80          movem.w d0-d3,$FF80(a5)             0/0
  4608:   //    00BFC8EA  206C0002              movea.l $0002(a4),a0                 l..
  4609:   //    00BFC8EE  2050                  movea.l (a0),a0                      P
  4610:   //    00BFC8F0  30280012              move.w  $0012(a0),d0                0(..
  4611:   //    00BFC8F4  5240                  addq.w  #$01,d0                     R@
  4612:   //    00BFC8F6  3B40FF90              move.w  d0,$FF90(a5)                ;@.食
  4613:   //    00BFC8FA  486DFFA4              pea.l   $FFA4(a5)                   Hm.、
  4614:   //    00BFC8FE  A432                  SXCALL  __SXGetDispRect             、2
  4615:   //    00BFC900  588F                  addq.l  #$04,sp                     X臭
  4616:   //    00BFC902  4CAD000FFFA4          movem.w $FFA4(a5),d0-d3             Lュ...、  ←ここでd1レジスタの上位ワードがほぼ0になる
  4617:   //    00BFC908  9641                  sub.w   d1,d3                       泡
  4618:   //    00BFC90A  48C3                  ext.l   d3                          Hテ      ←このサブルーチンはext.lで符号拡張してからdivu.wを使っているが、符号拡張しておいて符号なし除算というのもおかしい。movem.wでd3も符号拡張されているのでこのext.lは不要で、0<=d1.w<=d3.wでないときもext.lは役に立たない
  4619:   //    00BFC90C  86FC0010              divu.w  #$0010,d3                   ※..
  4620:   //    (以下略)
  4621:   //
  4622:   public static final boolean MPU_SXMENU = false;  //true=対策を施す。movem.w <ea>,<list>を修正して実害がなくなったので外しておく
  4623: 
  4624:   //mpuInit ()
  4625:   //  MPUを初期化する
  4626:   public static void mpuInit () {
  4627:     //コア
  4628:     mpuIgnoreAddressError = false;
  4629:     //レジスタ
  4630:     //r = new int[16];
  4631:     //FPU
  4632:     fpuInit ();  //FPU FPU
  4633:     //クロック
  4634:     mpuClockTime = 0L;
  4635:     mpuClockLimit = 0L;
  4636:     mpuCycleCount = 0;
  4637:     //タイマ
  4638:     mpuTask = null;
  4639:     //例外処理
  4640:     M68kException.m6eSignal = new M68kException ();
  4641:     M68kException.m6eNumber = 0;
  4642:     M68kException.m6eAddress = 0;
  4643:     M68kException.m6eDirection = MPU_WR_WRITE;
  4644:     M68kException.m6eSize = MPU_SS_BYTE;
  4645:     //その他
  4646:     mpuBootDevice = -1;
  4647:     mpuROMBootHandle = -1;
  4648:     mpuSavedBootDevice = -1;
  4649:     mpuSavedROMBootHandle = -1;
  4650:     //任意の周波数の指定
  4651:     //mpuArbFreqOn = !(clockMHz == 10.0 ||
  4652:     //                 clockMHz == 50.0 / 3.0 ||  //16.7MHz
  4653:     //                 clockMHz == 25.0 ||
  4654:     //                 clockMHz == 100.0 / 3.0 ||  //33.3MHz
  4655:     //                 clockMHz == 50.0 ||
  4656:     //                 clockMHz == 200.0 / 3.0 ||  //66.7MHz
  4657:     //                 clockMHz == 75.0 ||
  4658:     //                 clockMHz == 100.0);
  4659:     //mpuArbFreqMHz = mpuArbFreqOn ? (int) clockMHz : 100;
  4660:     //任意の負荷率の指定
  4661:     //mpuUtilOn = false;
  4662:     //mpuUtilRatio = 100;
  4663: 
  4664:     //カウンタ
  4665:     mpuAdjustmentCounter = MPU_ADJUSTMENT_INTERVAL;
  4666:     mpuTotalNano = 0L;
  4667:     mpuLastNano = System.nanoTime ();
  4668:     mpuCoreNano1 = mpuCoreNano2 = 0.5 * 1e+6 * (double) (TMR_INTERVAL * MPU_ADJUSTMENT_INTERVAL);  //負荷率50%
  4669: 
  4670:     mpuButtonsRunning = new ArrayList<AbstractButton> ();
  4671:     mpuButtonsStopped = new ArrayList<AbstractButton> ();
  4672: 
  4673:     mpuOriIllegalCheckBoxList = new ArrayList<JCheckBox> ();
  4674:     mpuStopOnErrorCheckBoxList = new ArrayList<JCheckBox> ();
  4675:     mpuStopAtStartCheckBoxList = new ArrayList<JCheckBox> ();
  4676: 
  4677:     mpuAdvanceCount = 0;
  4678:     mpuStepCount = 0;
  4679:     mpuContinue = false;
  4680:     mpuUntilReturnSRS = 0;
  4681:     mpuUntilReturnRP = 0;
  4682:     mpuUntilReturnPC0 = 0;
  4683:     mpuUntilReturnSP = 0;
  4684: 
  4685:     //デバッグアクションリスナー
  4686:     mpuDebugActionListener = new ActionListener () {
  4687:       @Override public void actionPerformed (ActionEvent ae) {
  4688:         Object source = ae.getSource ();
  4689:         switch (ae.getActionCommand ()) {
  4690:         case "Stop":  //停止
  4691:           if (RootPointerList.RTL_ON) {
  4692:             if (RootPointerList.rtlCurrentSupervisorTaskIsStoppable ||
  4693:                 RootPointerList.rtlCurrentUserTaskIsStoppable) {
  4694:               mpuStop (null);  //"Stop Button"
  4695:             }
  4696:           } else {
  4697:             mpuStop (null);  //"Stop Button"
  4698:           }
  4699:           break;
  4700:         case "Trace":  //トレース
  4701:           mpuAdvance (1);
  4702:           break;
  4703:         case "Trace 10 times":  //トレース 10 回
  4704:           mpuAdvance (10);
  4705:           break;
  4706:         case "Trace 100 times":  //トレース 100 回
  4707:           mpuAdvance (100);
  4708:           break;
  4709:         case "Step":  //ステップ
  4710:           mpuStep (1);
  4711:           break;
  4712:         case "Step 10 times":  //ステップ 10 回
  4713:           mpuStep (10);
  4714:           break;
  4715:         case "Step 100 times":  //ステップ 100 回
  4716:           mpuStep (100);
  4717:           break;
  4718:         case "Step until return":  //ステップアンティルリターン
  4719:           mpuStepUntilReturn ();
  4720:           break;
  4721:         case "Run":  //実行
  4722:           mpuStart ();
  4723:           break;
  4724:           //
  4725:         case "Consider ORI.B #$00,D0 as an illegal instruction" :
  4726:           if (XEiJ.DBG_ORI_BYTE_ZERO_D0) {
  4727:             dbgOriByteZeroD0 = ((JCheckBox) source).isSelected ();
  4728:             for (JCheckBox checkBox : mpuOriIllegalCheckBoxList) {
  4729:               if (checkBox.isSelected () != dbgOriByteZeroD0) {
  4730:                 checkBox.setSelected (dbgOriByteZeroD0);
  4731:               }
  4732:             }
  4733:           }
  4734:           break;
  4735:         case "Stop on error":
  4736:           dbgStopOnError = ((JCheckBox) source).isSelected ();
  4737:           for (JCheckBox checkBox : mpuStopOnErrorCheckBoxList) {
  4738:             if (checkBox.isSelected () != dbgStopOnError) {
  4739:               checkBox.setSelected (dbgStopOnError);
  4740:             }
  4741:           }
  4742:           break;
  4743:         case "Stop at execution start position":
  4744:           dbgStopAtStart = ((JCheckBox) source).isSelected ();
  4745:           for (JCheckBox checkBox : mpuStopAtStartCheckBoxList) {
  4746:             if (checkBox.isSelected () != dbgStopAtStart) {
  4747:               checkBox.setSelected (dbgStopAtStart);
  4748:             }
  4749:           }
  4750:           break;
  4751:         }
  4752:       }  //actionPerformed(ActionEvent)
  4753:     };  //mpuDebugActionListener
  4754: 
  4755:   }  //mpuInit()
  4756: 
  4757:   //mpuMakeOriIllegalCheckBox ()
  4758:   //  ORI.B #$00,D0を不当命令とみなすチェックボックスを作る
  4759:   public static JCheckBox mpuMakeOriIllegalCheckBox () {
  4760:     JCheckBox checkBox = Multilingual.mlnToolTipText (
  4761:       ComponentFactory.createIconCheckBox (
  4762:         DBG_ORI_BYTE_ZERO_D0 ? dbgOriByteZeroD0 : null,
  4763:         LnF.LNF_ORI_BYTE_ZERO_D0_IMAGE,
  4764:         LnF.LNF_ORI_BYTE_ZERO_D0_SELECTED_IMAGE,
  4765:         "Consider ORI.B #$00,D0 as an illegal instruction", mpuDebugActionListener),
  4766:       "ja", "ORI.B #$00,D0 を不当命令とみなす");
  4767:     mpuOriIllegalCheckBoxList.add (checkBox);
  4768:     return checkBox;
  4769:   }  //mpuMakeOriIllegalCheckBox
  4770: 
  4771:   //mpuMakeStopOnErrorCheckBox ()
  4772:   //  エラーで停止するチェックボックスを作る
  4773:   public static JCheckBox mpuMakeStopOnErrorCheckBox () {
  4774:     JCheckBox checkBox = Multilingual.mlnToolTipText (
  4775:       ComponentFactory.createIconCheckBox (
  4776:         dbgStopOnError,
  4777:         LnF.LNF_STOP_ON_ERROR_IMAGE,
  4778:         LnF.LNF_STOP_ON_ERROR_SELECTED_IMAGE,
  4779:         "Stop on error", mpuDebugActionListener),
  4780:       "ja", "エラーで停止する");
  4781:     mpuStopOnErrorCheckBoxList.add (checkBox);
  4782:     return checkBox;
  4783:   }  //mpuMakeStopOnErrorCheckBox
  4784: 
  4785:   //mpuMakeStopAtStartCheckBox ()
  4786:   //  実行開始位置で停止するチェックボックスを作る
  4787:   public static JCheckBox mpuMakeStopAtStartCheckBox () {
  4788:     JCheckBox checkBox = Multilingual.mlnToolTipText (
  4789:       ComponentFactory.createIconCheckBox (
  4790:         dbgStopAtStart,
  4791:         LnF.LNF_STOP_AT_START_IMAGE,
  4792:         LnF.LNF_STOP_AT_START_SELECTED_IMAGE,
  4793:         "Stop at execution start position", mpuDebugActionListener),
  4794:       "ja", "実行開始位置で停止する");
  4795:     mpuStopAtStartCheckBoxList.add (checkBox);
  4796:     return checkBox;
  4797:   }  //mpuMakeStopAtStartCheckBox
  4798: 
  4799:   //mpuMakeMenu ()
  4800:   public static void mpuMakeMenu () {
  4801:     //メニュー
  4802:     ButtonGroup unitGroup = new ButtonGroup ();
  4803:     ActionListener listener = new ActionListener () {
  4804:       @Override public void actionPerformed (ActionEvent ae) {
  4805:         Object source = ae.getSource ();
  4806:         switch (ae.getActionCommand ()) {
  4807:         case "Reset":  //リセット
  4808:           mpuReset (-1, -1);
  4809:           break;
  4810:         case "Hold down OPT.1 and reset":  //OPT.1 を押しながらリセット
  4811:           mpuReset (0, -1);
  4812:           break;
  4813:         case "Interrupt":  //インタラプト
  4814:           sysInterrupt ();  //インタラプトスイッチが押された
  4815:           break;
  4816:         case "10MHz":
  4817:           mpuArbFreqOn = false;
  4818:           mpuUtilOn = false;
  4819:           mpuSetCurrentClock (10.0);
  4820:           break;
  4821:         case "16.7MHz":
  4822:           mpuArbFreqOn = false;
  4823:           mpuUtilOn = false;
  4824:           mpuSetCurrentClock (50.0 / 3.0);  //16.7MHz
  4825:           break;
  4826:         case "25MHz":
  4827:           mpuArbFreqOn = false;
  4828:           mpuUtilOn = false;
  4829:           mpuSetCurrentClock (25.0);
  4830:           break;
  4831:         case "33.3MHz":
  4832:           mpuArbFreqOn = false;
  4833:           mpuUtilOn = false;
  4834:           mpuSetCurrentClock (100.0 / 3.0);  //33.3MHz
  4835:           break;
  4836:         case "50MHz":
  4837:           mpuArbFreqOn = false;
  4838:           mpuUtilOn = false;
  4839:           mpuSetCurrentClock (50.0);
  4840:           break;
  4841:         case "66.7MHz":
  4842:           mpuArbFreqOn = false;
  4843:           mpuUtilOn = false;
  4844:           mpuSetCurrentClock (200.0 / 3.0);  //66.7MHz
  4845:           break;
  4846:         case "75MHz":
  4847:           mpuArbFreqOn = false;
  4848:           mpuUtilOn = false;
  4849:           mpuSetCurrentClock (75.0);
  4850:           break;
  4851:         case "100MHz":
  4852:           mpuArbFreqOn = false;
  4853:           mpuUtilOn = false;
  4854:           mpuSetCurrentClock (100.0);
  4855:           break;
  4856:         case "Arbitrary frequency":  //任意の周波数
  4857:           mpuArbFreqOn = true;
  4858:           mpuUtilOn = false;
  4859:           mpuSetCurrentClock ((double) mpuArbFreqMHz);
  4860:           break;
  4861:         case "Arbitrary load factor":  //任意の負荷率
  4862:           mpuArbFreqOn = false;
  4863:           mpuUtilOn = true;
  4864:           break;
  4865:         case "FE function instruction":  //FE ファンクション命令
  4866:           FEFunction.fpkOn = ((JCheckBoxMenuItem) source).isSelected ();
  4867:           break;
  4868:         case "Reject FLOATn.X":  //FLOATn.X を組み込まない
  4869:           FEFunction.fpkRejectFloatOn = ((JCheckBoxMenuItem) source).isSelected ();
  4870:           break;
  4871:         case "Cut FC2 pin":  //FC2 ピンをカットする
  4872:           busRequestCutFC2Pin = ((JCheckBoxMenuItem) source).isSelected ();
  4873:           break;
  4874:         case "Wait cycles":  //ウェイトサイクル
  4875:           busWaitCyclesRequest = ((JCheckBoxMenuItem) source).isSelected ();
  4876:           break;
  4877:         case "Use IPLROM 1.6":  //IPLROM 1.6 を使う
  4878:           ROM.romIPLROM16On = ((JCheckBoxMenuItem) source).isSelected ();
  4879:           break;
  4880:         case "Increase IPLROM to 256KB":  //IPLROM を 256KB に増やす
  4881:           ROM.romIPLROM256KOn = ((JCheckBoxMenuItem) source).isSelected ();
  4882:           break;
  4883: 
  4884:         case "Run / Stop":  //実行/停止
  4885:           if (((JCheckBox) source).isSelected ()) {  //Run
  4886:             mpuStart ();
  4887:           } else {  //Stop
  4888:             if (RootPointerList.RTL_ON) {
  4889:               if (RootPointerList.rtlCurrentSupervisorTaskIsStoppable ||
  4890:                   RootPointerList.rtlCurrentUserTaskIsStoppable) {
  4891:                 mpuStop (null);  //"Stop Button"
  4892:               }
  4893:             } else {
  4894:               mpuStop (null);  //"Stop Button"
  4895:             }
  4896:           }
  4897:           pnlPanel.requestFocusInWindow ();  //パネルにフォーカスを戻す。戻さないとキー入力が入らない
  4898:           break;
  4899:         }
  4900:       }
  4901:     };
  4902:     mpuMenu = ComponentFactory.createMenu (
  4903:       "MPU", 'M',
  4904:       mpuResetMenuItem = Multilingual.mlnText (ComponentFactory.createMenuItem ("Reset", 'R', MNB_MODIFIERS, listener), "ja", "リセット"),
  4905:       mpuOpt1ResetMenuItem = Multilingual.mlnText (ComponentFactory.createMenuItem ("Hold down OPT.1 and reset", 'O', MNB_MODIFIERS, listener), "ja", "OPT.1 を押しながらリセット"),
  4906:       Multilingual.mlnText (ComponentFactory.createMenuItem ("Interrupt", listener), "ja", "インタラプト"),
  4907:       ComponentFactory.createHorizontalSeparator (),
  4908:       mdlMenu,
  4909:       ComponentFactory.createHorizontalSeparator (),
  4910:       mpuClock10MenuItem = ComponentFactory.createRadioButtonMenuItem (
  4911:         unitGroup,
  4912:         !mpuArbFreqOn && !mpuUtilOn && specifiedClock == 10.0,
  4913:         "10MHz",
  4914:         listener),
  4915:       mpuClock16MenuItem = ComponentFactory.createRadioButtonMenuItem (
  4916:         unitGroup,
  4917:         !mpuArbFreqOn && !mpuUtilOn && specifiedClock == 50.0 / 3.0,
  4918:         "16.7MHz",
  4919:         listener),
  4920:       mpuClock25MenuItem = ComponentFactory.createRadioButtonMenuItem (
  4921:         unitGroup,
  4922:         !mpuArbFreqOn && !mpuUtilOn && specifiedClock == 25.0,
  4923:         "25MHz",
  4924:         listener),
  4925:       mpuClock33MenuItem = ComponentFactory.createRadioButtonMenuItem (
  4926:         unitGroup,
  4927:         !mpuArbFreqOn && !mpuUtilOn && specifiedClock == 100.0 / 3.0,
  4928:         "33.3MHz",
  4929:         listener),
  4930:       mpuClock50MenuItem = ComponentFactory.createRadioButtonMenuItem (
  4931:         unitGroup,
  4932:         !mpuArbFreqOn && !mpuUtilOn && specifiedClock == 50.0,
  4933:         "50MHz",
  4934:         listener),
  4935:       mpuClock66MenuItem = ComponentFactory.createRadioButtonMenuItem (
  4936:         unitGroup,
  4937:         !mpuArbFreqOn && !mpuUtilOn && specifiedClock == 200.0 / 3.0,
  4938:         "66.7MHz",
  4939:         listener),
  4940:       mpuClock75MenuItem = ComponentFactory.createRadioButtonMenuItem (
  4941:         unitGroup,
  4942:         !mpuArbFreqOn && !mpuUtilOn && specifiedClock == 75.0,
  4943:         "75MHz",
  4944:         listener),
  4945:       mpuClock100MenuItem = ComponentFactory.createRadioButtonMenuItem (
  4946:         unitGroup,
  4947:         !mpuArbFreqOn && !mpuUtilOn && specifiedClock == 100.0,
  4948:         "100MHz",
  4949:         listener),
  4950:       mpuArbFreqRadioButtonMenuItem = Multilingual.mlnText (
  4951:         ComponentFactory.createRadioButtonMenuItem (
  4952:           unitGroup,
  4953:           mpuArbFreqOn,
  4954:           "Arbitrary frequency",
  4955:           listener),
  4956:         "ja", "任意の周波数"),
  4957:       ComponentFactory.createHorizontalBox (
  4958:         Box.createHorizontalStrut (20),
  4959:         mpuArbFreqSpinner = ComponentFactory.createNumberSpinner (
  4960:           mpuArbFreqModel = new SpinnerNumberModel (mpuArbFreqMHz, 1, 1000, 1),
  4961:           4,
  4962:           new ChangeListener () {
  4963:             @Override public void stateChanged (ChangeEvent ce) {
  4964:               //mpuArbFreqRadioButtonMenuItem.setSelected (true);
  4965:               mpuArbFreqMHz = mpuArbFreqModel.getNumber ().intValue ();
  4966:               if (mpuArbFreqOn) {
  4967:                 mpuSetCurrentClock ((double) mpuArbFreqMHz);
  4968:               }
  4969:             }
  4970:           }
  4971:           ),
  4972:         ComponentFactory.createLabel ("MHz"),
  4973:         Box.createHorizontalGlue ()
  4974:         ),
  4975:       mpuUtilRadioButtonMenuItem = Multilingual.mlnText (
  4976:         ComponentFactory.createRadioButtonMenuItem (
  4977:           unitGroup,
  4978:           mpuUtilOn,
  4979:           "Arbitrary load factor",
  4980:           listener),
  4981:         "ja", "任意の負荷率"),
  4982:       ComponentFactory.createHorizontalBox (
  4983:         Box.createHorizontalStrut (20),
  4984:         mpuUtilSpinner = ComponentFactory.createNumberSpinner (
  4985:           mpuUtilModel = new SpinnerNumberModel (mpuUtilRatio, 1, 100, 1),
  4986:           4,
  4987:           new ChangeListener () {
  4988:             @Override public void stateChanged (ChangeEvent ce) {
  4989:               //mpuUtilRadioButtonMenuItem.setSelected (true);
  4990:               mpuUtilRatio = mpuUtilModel.getNumber ().intValue ();
  4991:             }
  4992:           }
  4993:           ),
  4994:         ComponentFactory.createLabel ("%"),
  4995:         Box.createHorizontalGlue ()
  4996:         ),
  4997:       ComponentFactory.createHorizontalSeparator (),
  4998:       fpuMenuItem0,
  4999:       fpuMenuItem1,
  5000:       fpuMenuItem2,
  5001:       fpuMenuItem3,
  5002:       Multilingual.mlnText (ComponentFactory.createCheckBoxMenuItem (FEFunction.fpkOn, "FE function instruction", listener), "ja", "FE ファンクション命令"),
  5003:       Multilingual.mlnText (ComponentFactory.createCheckBoxMenuItem (FEFunction.fpkRejectFloatOn, "Reject FLOATn.X", listener), "ja", "FLOATn.X を組み込まない"),
  5004:       ComponentFactory.createHorizontalSeparator (),
  5005:       Multilingual.mlnText (ComponentFactory.createCheckBoxMenuItem (busRequestCutFC2Pin, "Cut FC2 pin", listener), "ja", "FC2 ピンをカットする"),
  5006:       Multilingual.mlnText (ComponentFactory.createCheckBoxMenuItem (busWaitCyclesRequest, "Wait cycles", listener), "ja", "ウェイトサイクル"),
  5007:       ComponentFactory.createHorizontalSeparator (),
  5008:       Multilingual.mlnText (ComponentFactory.createCheckBoxMenuItem (ROM.romIPLROM16On, "Use IPLROM 1.6", listener), "ja", "IPLROM 1.6 を使う"),
  5009:       Multilingual.mlnText (ComponentFactory.createCheckBoxMenuItem (ROM.romIPLROM256KOn, "Increase IPLROM to 256KB", listener), "ja", "IPLROM を 256KB に増やす")
  5010:       );
  5011:   }  //mpuMakeMenu()
  5012: 
  5013:   //  クロック(MHz)を設定する
  5014:   public static void mpuSetCurrentClock (double clock) {
  5015:     specifiedClock = clock;
  5016:     if (currentIsSecond) {
  5017:       specifiedSecondClock = clock;
  5018:     } else {
  5019:       specifiedFirstClock = clock;
  5020:     }
  5021:     if (!mpuArbFreqOn && !mpuUtilOn) {
  5022:       if (specifiedClock == 10.0) {
  5023:         mpuClock10MenuItem.setSelected (true);
  5024:       } else if (specifiedClock == 50.0 / 3.0) {  //16.7MHz
  5025:         mpuClock16MenuItem.setSelected (true);
  5026:       } else if (specifiedClock == 25.0) {
  5027:         mpuClock25MenuItem.setSelected (true);
  5028:       } else if (specifiedClock == 100.0 / 3.0) {  //33.3MHz
  5029:         mpuClock33MenuItem.setSelected (true);
  5030:       } else if (specifiedClock == 50.0) {
  5031:         mpuClock50MenuItem.setSelected (true);
  5032:       } else if (specifiedClock == 200.0 / 3.0) {  //66.7MHz
  5033:         mpuClock66MenuItem.setSelected (true);
  5034:       } else if (specifiedClock == 75.0) {
  5035:         mpuClock75MenuItem.setSelected (true);
  5036:       } else if (specifiedClock == 100.0) {
  5037:         mpuClock100MenuItem.setSelected (true);
  5038:       }
  5039:     }
  5040:     mpuClockMHz = specifiedClock;
  5041:     mpuSetClockMHz (mpuClockMHz);  //currentMPUが変更されたときは再計算が必要なのでクロックが変わっていなくても省略できない
  5042:   }
  5043: 
  5044:   //mpuSetClockMHz (mhz)
  5045:   //  mpuCurrentMHz,mpuCycleUnit,mpuModifiedUnitを設定する
  5046:   //  TMR_FREQ=10^12のとき
  5047:   //               mpuModifiedUnitと1サイクルの時間
  5048:   //  mpuClockMHz     000/060         030
  5049:   //    10.0MHz    100000(100ns)  60000(60ns)
  5050:   //    16.7MHz     60000 (60ns)  36000(36ns)
  5051:   //    25.0MHz     40000 (40ns)  24000(24ns)
  5052:   //    33.3MHz     30000 (30ns)  18000(18ns)
  5053:   //    50.0MHz     20000 (20ns)  12000(12ns)
  5054:   public static void mpuSetClockMHz (double mhz) {
  5055:     mhz = Math.max (1.0, Math.min (1000.0, mhz));
  5056:     double lastMHz = mpuCurrentMHz;
  5057:     mpuCurrentMHz = mhz;
  5058:     mpuCycleUnit = (long) (((double) TMR_FREQ / 1000000.0) / mhz + 0.5);
  5059:     //  DBRA命令で比較するとMC68030は3/5、MC68040は2/5、MC68060は1/5くらい?
  5060:     mpuModifiedUnit = (currentMPU == Model.MPU_MC68EC030 ||
  5061:                        currentMPU == Model.MPU_MC68030 ?
  5062:                        (long) (((double) TMR_FREQ * 3.0 / (5.0 * 1000000.0)) / mhz + 0.5) :
  5063:                        currentMPU == Model.MPU_MC68LC040 ||
  5064:                        currentMPU == Model.MPU_MC68040 ?
  5065:                        (long) (((double) TMR_FREQ * 2.0 / (5.0 * 1000000.0)) / mhz + 0.5) :
  5066:                        mpuCycleUnit);
  5067:     if (lastMHz != mhz) {
  5068:       mpuSetWait ();
  5069:     }
  5070:   }  //mpuSetClockMHz(double)
  5071: 
  5072:   //mpuSetWait ()
  5073:   //  ウェイトを設定する
  5074:   //    currentMPU
  5075:   //    mpuCycleUnit
  5076:   //    mpuCacheOn
  5077:   //    mpuROMWaitCycles
  5078:   //    mpuRAMWaitCycles
  5079:   //    dmaCycleUnit
  5080:   //  から
  5081:   //    mpuWaitTime
  5082:   //    dmaWaitTime
  5083:   //  のすべての項目と
  5084:   //    mpuNoWaitTime
  5085:   //  のsramとromを作る
  5086:   //!!! 機種や個体による違いは考慮されていない。DMACのウェイトの機種による違いはDMAC側で調整している
  5087:   //!!! 状態やアクセス方法による違いは考慮されていない
  5088:   //!!! MPUで分類しておりXellent30は考慮されていない
  5089:   //!!! X68030のramとromはロングワード境界を跨がなければ1回でアクセスできるが考慮されていない
  5090:   //!!! 060turboはI/Oポートの書き込みウェイトの間に多数の命令を実行できるが考慮されていない
  5091:   //  参考
  5092:   //                         Execution time of instructions testing I/O ports
  5093:   //    +---------------+-------------------+----------------------------------------------------+
  5094:   //    |               |                   |                execution time (us)                 |
  5095:   //    |   I/O port    |    instruction    |           X68000 10MHz            | X68030 060turbo|
  5096:   //    |               |                   | Shodai  ACE  ACE 2nd  PRO    XVI  | 25MHz   50MHz  |
  5097:   //    +---------------+-------------------+-----------------------------------+----------------+
  5098:   //    | main memory   | tst.w $00000000.l | 1.642  1.642  1.643  1.663  1.650 | 0.2400  0.0399 |
  5099:   //    | GVRAM         | tst.w $00C00000.l | 1.752  1.750  1.750  1.770  1.734 | 0.4951  0.4700 |
  5100:   //    | TVRAM         | tst.w $00E00000.l | 1.829  1.849  1.850  1.840  1.848 | 0.5049  0.4800 |
  5101:   //    | CRTC R00      | tst.w $00E80000.l | 1.740  1.724  1.726  1.770  1.733 | 0.4800  0.4599 |
  5102:   //    | CRTC action   | tst.w $00E80480.l | 1.741  1.725  1.725  1.771  1.733 | 0.4800  0.4600 |
  5103:   //    | VCN gpalet    | tst.w $00E82000.l | 1.875  1.909  1.910  1.912  1.919 | 0.6778  0.6962 |
  5104:   //    | VCN mode      | tst.w $00E82400.l | 1.641  1.640  1.642  1.770  1.733 | 0.4800  0.4601 |
  5105:   //    | DMAC ch0 CSR  | tst.b $00E84000.l | 3.124  3.114  3.115  3.127  3.124 | 1.599   1.501  |
  5106:   //    | MFP GPIP      | tst.b $00E88001.l | 2.088  2.031  2.031  2.082  2.080 | 1.013   0.9801 |
  5107:   //    | RTC onesec    | tst.b $00E8A001.l | 1.776  1.850  1.851  1.773  1.836 | 1.359   1.580  |
  5108:   //    | PRN data      | tst.b $00E8C001.l | 1.742  1.725  1.725  1.771  1.734 | 0.4001  0.3800 |
  5109:   //    | SYS contrast  | tst.b $00E8E001.l | 1.741  1.725  1.726  1.771  1.734 | 0.4000  0.3800 |
  5110:   //    | OPM status    | tst.b $00E90003.l | 1.776  1.852  1.850  1.772  1.835 | 0.8268  0.7801 |
  5111:   //    | PCM status    | tst.b $00E92001.l | 1.776  1.850  1.850  1.771  1.836 | 0.8268  0.7800 |
  5112:   //    | FDC status    | tst.b $00E94001.l | 1.776  1.852  1.850  1.771  1.836 | 0.8266  0.7800 |
  5113:   //    | FDD status    | tst.b $00E94005.l | 1.777  1.850  1.850  1.770  1.836 | 0.8268  0.7801 |
  5114:   //    | HDC status    | tst.b $00E96003.l | 1.776  1.852  1.850  1.770  1.836 | 0.8267  0.7801 |
  5115:   //    | SCC chB RR0   | tst.b $00E98001.l | 2.231  2.234  2.236  2.248  2.244 | 1.760   1.980  |
  5116:   //    | PPI portA     | tst.b $00E9A001.l | 1.777  1.851  1.852  1.771  1.835 | 0.8268  0.7800 |
  5117:   //    | IOI status    | tst.b $00E9C001.l | 1.776  1.851  1.851  1.770  1.835 | 0.8267  0.7800 |
  5118:   //    | SPRC bg0 scrX | tst.w $00EB0800.l | 1.740  1.725  1.726  1.769  1.734 | 0.4800  0.4600 |
  5119:   //    | SRAM          | tst.w $00ED0000.l | 1.741  1.725  1.725  1.772  1.733 | 0.3199  0.3001 |
  5120:   //    | CGROM         | tst.w $00F00000.l | 1.741  1.725  1.725  1.771  1.733 | 0.2399  0.0400 |
  5121:   //    | IPLROM        | tst.w $00FF0000.l | 1.742  1.726  1.725  1.770  1.734 | 0.2400  0.0400 |
  5122:   //    +---------------+-------------------+-----------------------------------+----------------+
  5123:   //    thanks to uchopon, tnb and ita
  5124:   //
  5125:   //                    X68000   X68030 060turbo
  5126:   //                     10MHz    25MHz    50MHz
  5127:   //    main memory      0.123    0.000    0.000
  5128:   //    GVRAM            1.145    6.377   21.500
  5129:   //    TVRAM            2.046    6.623   22.000
  5130:   //    CRTC R00         1.050    6.000   20.995
  5131:   //    CRTC action      1.055    6.000   21.000
  5132:   //    VCN gpalet       2.668   10.945   32.810
  5133:   //    VCN mode         0.592    6.000   21.005
  5134:   //    DMAC ch0 CSR    14.853   33.975   73.050
  5135:   //    MFP GPIP         4.332   19.325   47.005
  5136:   //    RTC onesec       1.718   27.975   77.000
  5137:   //    PRN data         1.060    4.002   17.000
  5138:   //    SYS contrast     1.058    4.000   17.000
  5139:   //    OPM status       1.715   14.670   37.005
  5140:   //    PCM status       1.712   14.670   37.000
  5141:   //    FDC status       1.715   14.665   37.000
  5142:   //    FDD status       1.712   14.670   37.005
  5143:   //    HDC status       1.712   14.668   37.005
  5144:   //    SCC chB RR0      6.025   38.000   97.000
  5145:   //    PPI portA        1.716   14.670   37.000
  5146:   //    IOI status       1.710   14.668   37.000
  5147:   //    SPRC bg0 scrX    1.051    6.000   21.000
  5148:   //    SRAM             1.057    1.998   13.005
  5149:   //    CGROM            1.055   -0.002    0.000
  5150:   //    IPLROM           1.058    0.000    0.000
  5151:   //
  5152:   public static void mpuSetWait () {
  5153:     //MPU
  5154:     if (currentMPU <= Model.MPU_MC68010) {  //68000/68010
  5155:       mpuWaitTime.ram = mpuCycleUnit >> 3;  //DRAMリフレッシュウェイトを1/8サイクル/ワードとする
  5156:       mpuWaitTime.vicon = (long) (mpuCycleUnit * 0.6);
  5157:       mpuWaitTime.crtc =
  5158:         mpuWaitTime.prnport =
  5159:           mpuWaitTime.sysport =
  5160:             mpuWaitTime.sprc =
  5161:               mpuWaitTime.sram =
  5162:                 mpuWaitTime.rom = mpuCycleUnit;
  5163:       mpuWaitTime.gvram = (long) (mpuCycleUnit * 1.1);
  5164:       mpuWaitTime.rtc =
  5165:         mpuWaitTime.opm =
  5166:           mpuWaitTime.adpcm =
  5167:             mpuWaitTime.fdc =
  5168:               mpuWaitTime.fdd =
  5169:                 mpuWaitTime.hdc =
  5170:                   mpuWaitTime.ppi =
  5171:                     mpuWaitTime.ioi = (long) (mpuCycleUnit * 1.7);
  5172:       mpuWaitTime.tvram = mpuCycleUnit * 2;
  5173:       mpuWaitTime.palet = (long) (mpuCycleUnit * 2.6);
  5174:       mpuWaitTime.mfp = (long) (mpuCycleUnit * 4.3);
  5175:       mpuWaitTime.scc = mpuCycleUnit * 6;
  5176:       mpuWaitTime.dmac = mpuCycleUnit * 15;
  5177:       mpuWaitTime.ramlong = mpuWaitTime.ram << 1;
  5178:       mpuWaitTime.romlong = mpuWaitTime.rom << 1;
  5179:     } else if (currentMPU <= Model.MPU_MC68030) {  //68020/68030
  5180:       mpuWaitTime.ram = mpuCacheOn ? 0 : mpuCycleUnit * mpuRAMWaitCycles + (mpuCycleUnit >> 3);
  5181:       mpuWaitTime.rom = mpuCacheOn ? 0 : mpuCycleUnit * mpuROMWaitCycles;
  5182:       mpuWaitTime.sram = mpuCycleUnit * 2;
  5183:       mpuWaitTime.prnport =
  5184:         mpuWaitTime.sysport = mpuCycleUnit * 4;
  5185:       mpuWaitTime.gvram =
  5186:         mpuWaitTime.crtc =
  5187:           mpuWaitTime.vicon =
  5188:             mpuWaitTime.sprc = mpuCycleUnit * 6;
  5189:       mpuWaitTime.tvram = mpuCycleUnit * 7;
  5190:       mpuWaitTime.palet = mpuCycleUnit * 11;
  5191:       mpuWaitTime.opm =
  5192:         mpuWaitTime.adpcm =
  5193:           mpuWaitTime.fdc =
  5194:             mpuWaitTime.fdd =
  5195:               mpuWaitTime.hdc =
  5196:                 mpuWaitTime.ppi =
  5197:                   mpuWaitTime.ioi = mpuCycleUnit * 15;
  5198:       mpuWaitTime.mfp = mpuCycleUnit * 19;
  5199:       mpuWaitTime.rtc = mpuCycleUnit * 28;
  5200:       mpuWaitTime.dmac = mpuCycleUnit * 34;
  5201:       mpuWaitTime.scc = mpuCycleUnit * 38;
  5202:       mpuWaitTime.ramlong = mpuWaitTime.ram;
  5203:       mpuWaitTime.romlong = mpuWaitTime.rom;
  5204:     } else {  //68040/68060
  5205:       mpuWaitTime.ram = mpuCacheOn ? 0 : mpuCycleUnit * mpuRAMWaitCycles + (mpuCycleUnit >> 3);
  5206:       mpuWaitTime.rom = mpuCacheOn ? 0 : mpuCycleUnit * mpuROMWaitCycles;
  5207:       mpuWaitTime.sram = mpuCycleUnit * 13;
  5208:       mpuWaitTime.prnport =
  5209:         mpuWaitTime.sysport = mpuCycleUnit * 17;
  5210:       mpuWaitTime.gvram =
  5211:         mpuWaitTime.crtc =
  5212:           mpuWaitTime.vicon =
  5213:             mpuWaitTime.sprc = mpuCycleUnit * 21;
  5214:       mpuWaitTime.tvram = mpuCycleUnit * 22;
  5215:       mpuWaitTime.palet = mpuCycleUnit * 33;
  5216:       mpuWaitTime.opm =
  5217:         mpuWaitTime.adpcm =
  5218:           mpuWaitTime.fdc =
  5219:             mpuWaitTime.fdd =
  5220:               mpuWaitTime.hdc =
  5221:                 mpuWaitTime.ppi =
  5222:                   mpuWaitTime.ioi = mpuCycleUnit * 37;
  5223:       mpuWaitTime.mfp = mpuCycleUnit * 47;
  5224:       mpuWaitTime.dmac = mpuCycleUnit * 73;
  5225:       mpuWaitTime.rtc = mpuCycleUnit * 77;
  5226:       mpuWaitTime.scc = mpuCycleUnit * 97;
  5227:       mpuWaitTime.ramlong = mpuWaitTime.ram;
  5228:       mpuWaitTime.romlong = mpuWaitTime.rom;
  5229:     }
  5230:     if (true) {
  5231:       mpuNoWaitTime.sram = mpuWaitTime.sram;
  5232:       mpuNoWaitTime.rom = mpuWaitTime.rom;
  5233:       mpuNoWaitTime.romlong = mpuWaitTime.romlong;
  5234:     }
  5235:     //DMAC
  5236:     dmaWaitTime.ram = dmaCycleUnit >> 3;  //DRAMリフレッシュウェイトを1/8サイクル/ワードとする
  5237:     dmaWaitTime.sram = 0;
  5238:     dmaWaitTime.rom = 0;
  5239:     dmaWaitTime.gvram =
  5240:       dmaWaitTime.crtc =
  5241:         dmaWaitTime.vicon =
  5242:           dmaWaitTime.prnport =
  5243:             dmaWaitTime.sysport =
  5244:               dmaWaitTime.sprc = dmaCycleUnit;
  5245:     dmaWaitTime.tvram =
  5246:       dmaWaitTime.rtc =
  5247:         dmaWaitTime.opm =
  5248:           dmaWaitTime.adpcm =
  5249:             dmaWaitTime.fdc =
  5250:               dmaWaitTime.fdd =
  5251:                 dmaWaitTime.hdc =
  5252:                   dmaWaitTime.ppi =
  5253:                     dmaWaitTime.ioi = dmaCycleUnit * 2;
  5254:     dmaWaitTime.palet = dmaCycleUnit * 3;
  5255:     dmaWaitTime.mfp = dmaCycleUnit * 4;
  5256:     dmaWaitTime.scc = dmaCycleUnit * 6;
  5257:     dmaWaitTime.dmac = dmaCycleUnit * 15;
  5258:     dmaWaitTime.ramlong = dmaWaitTime.ram << 1;
  5259:     dmaWaitTime.romlong = dmaWaitTime.rom << 1;
  5260:   }  //mpuSetWait
  5261: 
  5262:   //mpuReset (device, romHandle)
  5263:   //  MPUをリセットしてからコアのタスクを起動する
  5264:   //  コアのタスクが動いているときはそれを中断する
  5265:   //  動いていたタスクが完全に止まってから再起動する
  5266:   public static void mpuReset (int device, int romHandle) {
  5267: 
  5268:     mpuBootDevice = device;
  5269:     mpuROMBootHandle = romHandle;
  5270: 
  5271:     //mpuBootDevice
  5272:     //  -1=リセット,0=OPT.1キーを押しながらリセット、その他=ここから再起動
  5273:     //  リセットのとき
  5274:     //    保存されている起動デバイスがあるとき
  5275:     //      起動デバイスを保存されている起動デバイスに変更する
  5276:     //      保存されている起動デバイスを消す
  5277:     //  リセット以外のとき
  5278:     //    保存されている起動デバイスがないとき
  5279:     //      起動デバイスを保存する
  5280:     //  メニューで起動デバイスが既定以外に設定されたとき
  5281:     //    保存されている起動デバイスを消す
  5282:     if (mpuBootDevice == -1) {  //リセットのとき
  5283:       if (mpuSavedBootDevice != -1) {  //保存されている起動デバイスがあるとき
  5284:         mpuBootDevice = mpuSavedBootDevice;  //起動デバイスを保存されている起動デバイスに変更する
  5285:         mpuROMBootHandle = mpuSavedROMBootHandle;
  5286:         mpuSavedBootDevice = -1;  //保存されている起動デバイスを消す
  5287:         mpuSavedROMBootHandle = -1;
  5288:       }
  5289:     } else {  //リセット以外のとき
  5290:       if (mpuSavedBootDevice == -1) {  //保存されている起動デバイスがないとき
  5291:         mpuSavedBootDevice = MainMemory.mmrRwz (0x00ed0018);  //起動デバイスを保存する
  5292:         mpuSavedROMBootHandle = MainMemory.mmrRls (0x00ed000c);
  5293:       }
  5294:     }
  5295: 
  5296:     //1番目のMPUを選択する
  5297:     specifiedIsSecond = false;
  5298:     specifiedMPU = specifiedIsSecond ? specifiedSecondMPU : specifiedFirstMPU;
  5299:     specifiedClock = specifiedIsSecond ? specifiedSecondClock : specifiedFirstClock;
  5300: 
  5301:     if (MC68EC030.M30_DIV_ZERO_V_FLAG) {
  5302:       MC68EC030.m30DivZeroVFlag = false;
  5303:     }
  5304: 
  5305:     if (mpuTask != null) {
  5306:       mpuClockLimit = 0L;
  5307:       System.out.println (Multilingual.mlnJapanese ?
  5308:                           "MPU を停止します" :
  5309:                           "MPU stops");
  5310:       mpuTask.cancel ();
  5311:       mpuTask = null;
  5312:     }
  5313: 
  5314:     tmrTimer.schedule (new TimerTask () {
  5315:       @Override public void run () {
  5316: 
  5317:         //リセット後の値を現在の値にする
  5318:         //  機種とアクセラレータ
  5319:         currentModel = specifiedModel;
  5320:         currentAccelerator = specifiedAccelerator;
  5321:         frmUpdateTitle ();
  5322:         //  MPU
  5323:         currentIsSecond = specifiedIsSecond;
  5324:         currentFirstMPU = specifiedFirstMPU;
  5325:         currentSecondMPU = specifiedSecondMPU;
  5326:         currentMPU = specifiedMPU;
  5327:         //  クロック(MHz)
  5328:         mpuSetCurrentClock (specifiedClock);
  5329:         //  FPUまたはFPCP
  5330:         currentFPU = specifiedFPU;
  5331:         currentTriplePrecision = specifiedTriplePrecision;
  5332:         currentFullSpecification = specifiedFullSpecification;
  5333: 
  5334:         //メモリマップを再構築する
  5335:         if (currentMPU < Model.MPU_MC68020) {
  5336:           if (busHimem68000) {
  5337:             busRequestExMemoryStart = 0x10000000;
  5338:             busRequestExMemorySize = busLocalMemorySize;
  5339:             busRequestExMemoryArray = busLocalMemoryArray;
  5340:           } else {
  5341:             busRequestExMemoryStart = 0x10000000;
  5342:             busRequestExMemorySize = 0 << 20;
  5343:             busRequestExMemoryArray = BUS_DUMMY_MEMORY_ARRAY;
  5344:           }
  5345:         } else if (currentMPU < Model.MPU_MC68LC040) {
  5346:           if (busHighMemory060turboOn) {
  5347:             busRequestExMemoryStart = 0x10000000;
  5348:             busRequestExMemorySize = busLocalMemorySize;
  5349:             busRequestExMemoryArray = busLocalMemoryArray;
  5350:           } else {
  5351:             busRequestExMemoryStart = 0x01000000;
  5352:             busRequestExMemorySize = busHighMemorySize;
  5353:             busRequestExMemoryArray = busHighMemoryArray;
  5354:           }
  5355:         } else {
  5356:           busRequestExMemoryStart = 0x10000000;
  5357:           busRequestExMemorySize = busLocalMemorySize;
  5358:           busRequestExMemoryArray = busLocalMemoryArray;
  5359:         }
  5360:         busUpdateMemoryMap ();
  5361: 
  5362:         //ROMを構築する
  5363:         ROM.romReset ();
  5364: 
  5365:         RegisterList.drpSetMPU ();
  5366: 
  5367:         mpuSFC = mpuDFC = mpuCACR = mpuBUSCR = mpuUSP = mpuVBR = mpuCAAR = mpuMSP = mpuISP = 0;
  5368:         mpuPCR = 0x04300500 | MPU_060_REV << 8;
  5369:         MC68060.mmuReset ();  //TCR,ITT0,ITT1,DTT0,DTT1,URP,SRP。060→000/030のときアドレス変換をOFFにする必要がある
  5370: 
  5371:         if (!currentModel.isX68030 ()) {  //X68000
  5372:           dmaCycleUnit = TMR_FREQ / 10000000L;  //DMACは10MHz
  5373:           HD63450.dmaBurstInterval = dmaCycleUnit << 4 + (HD63450.dmaBT >> 2);
  5374:           HD63450.dmaBurstSpan = HD63450.dmaBurstInterval >> 1 + (HD63450.dmaBR & 3);
  5375:           mpuROMWaitCycles = 1;
  5376:           mpuRAMWaitCycles = 0;
  5377:         } else {  //X68030
  5378:           dmaCycleUnit = TMR_FREQ / 12500000L;  //DMACは12.5MHz
  5379:           HD63450.dmaBurstInterval = dmaCycleUnit << 4 + (HD63450.dmaBT >> 2);
  5380:           HD63450.dmaBurstSpan = HD63450.dmaBurstInterval >> 1 + (HD63450.dmaBR & 3);
  5381:           mpuROMWaitCycles = 0;
  5382:           mpuRAMWaitCycles = 0;
  5383:         }
  5384: 
  5385:         busWaitCycles = busWaitCyclesRequest;
  5386:         busWaitTime = busWaitCycles ? mpuWaitTime : mpuNoWaitTime;
  5387: 
  5388:         HD63450.dmaReadCycles = (currentModel.isPRO () ? 6 :  //PROは6
  5389:                                  currentModel.isCompact () ? 4 :  //Compactは4
  5390:                                  5);  //その他は5
  5391:         HD63450.dmaWriteCycles = (currentModel.isPRO () ? 6 :  //PROは6
  5392:                                   5);  //その他は5
  5393: 
  5394:         if (currentMPU < Model.MPU_MC68020) {  //68000/68010
  5395: 
  5396:           mpuIgnoreAddressError = false;
  5397:           //mpuSFC = mpuDFC = mpuVBR = mpuISP = 0;
  5398:           mpuCacheOn = false;
  5399: 
  5400:         } else if (currentMPU < Model.MPU_MC68040) {  //68030
  5401: 
  5402:           mpuIgnoreAddressError = true;
  5403:           fpuBox = fpuMotherboardCoprocessor;
  5404:           if (currentFPU == 2) {
  5405:             fpuBox.epbSetMC68882 ();
  5406:           } else {
  5407:             fpuBox.epbSetMC68881 ();
  5408:           }
  5409:           if (currentTriplePrecision) {
  5410:             fpuBox.epbSetTriple ();
  5411:           } else {
  5412:             fpuBox.epbSetExtended ();
  5413:           }
  5414:           fpuBox.epbReset ();
  5415:           fpuFPn = fpuBox.epbFPn;
  5416:           //mpuCACR = mpuUSP = mpuVBR = mpuCAAR = mpuMSP = mpuISP = 0;
  5417:           mpuCacheOn = (mpuCACR & 0x00000101) != 0;
  5418: 
  5419:         } else {  //68040/68060
  5420: 
  5421:           mpuIgnoreAddressError = true;
  5422:           fpuBox = fpuOnChipFPU;
  5423:           if (currentFullSpecification) {
  5424:             fpuBox.epbSetFullSpec ();
  5425:             //} else if (currentMPU < Model.MPU_MC68LC060) {
  5426:             //  fpuBox.epbSetMC68040 ();
  5427:           } else {
  5428:             fpuBox.epbSetMC68060 ();
  5429:           }
  5430:           if (currentTriplePrecision) {
  5431:             fpuBox.epbSetTriple ();
  5432:           } else {
  5433:             fpuBox.epbSetExtended ();
  5434:           }
  5435:           fpuBox.epbReset ();
  5436:           fpuFPn = fpuBox.epbFPn;
  5437:           //mpuSFC = mpuDFC = mpuCACR = mpuBUSCR = mpuUSP = mpuVBR = mpuURP = mpuSRP = 0;
  5438:           mpuPCR = 0x04300500 | MPU_060_REV << 8;
  5439:           mpuCacheOn = (mpuCACR & 0x80008000) != 0;
  5440: 
  5441:         }
  5442: 
  5443:         mpuSetWait ();
  5444: 
  5445:         //! SSPとPCをROMのアドレスから直接読み出している
  5446:         regSRT1 = regSRT0 = 0;
  5447:         regSRS = REG_SR_S;
  5448:         regSRM = 0;
  5449:         regSRI = REG_SR_I;
  5450:         regCCR = 0;
  5451:         Arrays.fill (regRn, 0);
  5452:         //r[14] = 0x00001000;  //ROMDB2.32のバグ対策。コードにパッチをあてることにしたので不要
  5453:         regRn[15] = MainMemory.mmrRls (0x00ff0000);
  5454:         regPC = MainMemory.mmrRls (0x00ff0004);
  5455:         //メインメモリ
  5456:         MainMemory.mmrReset ();
  5457:         //バスコントローラ
  5458:         busReset ();
  5459:         if (InstructionBreakPoint.IBP_ON) {
  5460:           InstructionBreakPoint.ibpOp1MemoryMap = InstructionBreakPoint.ibpOp1SuperMap;
  5461:           InstructionBreakPoint.ibpReset ();
  5462:         }
  5463:         if (BranchLog.BLG_ON) {
  5464:           BranchLog.blgReset ();
  5465:         }
  5466:         //割り込み
  5467:         mpuIMR = 0;
  5468:         mpuIRR = 0;
  5469:         if (MC68901.MFP_DELAYED_INTERRUPT) {
  5470:           mpuDIRR = 0;
  5471:         }
  5472:         mpuISR = 0;
  5473:         //これでリセット命令が実行されるまでメインメモリとROM以外のデバイスは動かないはず
  5474:         //動作開始
  5475:         mpuStart ();
  5476:       }
  5477:     }, TMR_DELAY);
  5478: 
  5479:   }  //mpuReset(int,int)
  5480: 
  5481:   //mpuStart ()
  5482:   //  コアのタスクを起動する
  5483:   //  コアのタスクが動いているときはそれを中断する
  5484:   //  動いていたタスクが完全に止まってから再起動する
  5485:   public static void mpuStart () {
  5486:     if (mpuTask != null) {
  5487:       mpuClockLimit = 0L;
  5488:       System.out.println (Multilingual.mlnJapanese ?
  5489:                           "MPU を停止します" :
  5490:                           "MPU stops");
  5491:       mpuTask.cancel ();
  5492:       mpuTask = null;
  5493:     }
  5494:     //停止中だけ有効なボタンを無効にする
  5495:     for (AbstractButton button : mpuButtonsStopped) {
  5496:       button.setEnabled (false);
  5497:     }
  5498:     DisassembleList.ddpStoppedBy = null;
  5499:     System.out.println (Model.mpuNameOf (currentMPU) + (Multilingual.mlnJapanese ? " を起動します" : " starts up"));
  5500:     mpuTask = new TimerTask () {
  5501:       @Override public void run () {
  5502:         mpuContinue = true;
  5503:         mpuClockLimit = mpuClockTime + TMR_FREQ * TMR_INTERVAL / 1000;
  5504:         mpuExecuteCore ();
  5505:       }
  5506:     };
  5507:     tmrTimer.scheduleAtFixedRate (mpuTask, TMR_DELAY, TMR_INTERVAL);  //固定頻度実行
  5508:     //動作中だけ有効なボタンを有効にする
  5509:     for (AbstractButton button : mpuButtonsRunning) {
  5510:       button.setEnabled (true);
  5511:     }
  5512:   }  //mpuStart()
  5513: 
  5514:   //mpuExecuteCore ()
  5515:   //  コアを実行する
  5516:   public static void mpuExecuteCore () {
  5517:     //コアメーター計測開始
  5518:     long nanoStart = System.nanoTime ();
  5519:     //RTCを準備する
  5520:     busSuper (RP5C15.rtcFirst, 0x00e8a000, 0x00e8c000);  //RTC RTC
  5521:     //busSuperMap[0x00e8a000 >>> BUS_PAGE_BITS] = RP5C15.rtcFirst;
  5522:     //コアを呼び出す
  5523:     if (currentMPU < Model.MPU_MC68010) {
  5524:       MC68000.mpuCore ();
  5525:     } else if (currentMPU < Model.MPU_MC68020) {
  5526:       MC68010.mpuCore ();
  5527:     } else if (currentMPU < Model.MPU_MC68LC040) {
  5528:       MC68EC030.mpuCore ();
  5529:     } else {
  5530:       MC68060.mpuCore ();
  5531:     }
  5532:     //デバッグウインドウを更新する
  5533:     if (dbgVisibleMask != 0) {  //デバッグ関連ウインドウが表示されている
  5534:       dbgUpdate ();
  5535:     }
  5536:     //コアメーター計測終了
  5537:     long nanoEnd = System.nanoTime ();
  5538:     mpuTotalNano += nanoEnd - nanoStart;
  5539:     if (--mpuAdjustmentCounter == 0) {
  5540:       //本来の経過時間(ns)
  5541:       final double expectedNano = 1e+6 * (double) (TMR_INTERVAL * MPU_ADJUSTMENT_INTERVAL);
  5542:       //コアの所要時間(ns)
  5543:       double coreNano0 = (double) mpuTotalNano;
  5544:       mpuTotalNano = 0L;
  5545:       double coreNanoA = (coreNano0 * 2.0 + mpuCoreNano1 + mpuCoreNano2) * 0.25;  //コアの所要時間(ns)
  5546:       mpuCoreNano2 = mpuCoreNano1;
  5547:       mpuCoreNano1 = coreNano0;
  5548:       //現在の負荷率(%)
  5549:       //  現在の負荷率(%) = 100.0 * コアの所要時間(ns) / 本来の経過時間(ns)
  5550:       //  処理が間に合っていないとき100%よりも大きくなる
  5551:       double actualPercent = Math.max (1.0, 100.0 * coreNanoA / expectedNano);
  5552:       //負荷率の上限(%)
  5553:       double maxPercent = SoundSource.sndPlayOn ? 90.0 : 100.0;  //音声出力がONのとき90%、さもなくば100%
  5554:       //目標の動作周波数(MHz)
  5555:       //double targetMHz = mpuClockMHz;
  5556:       //現在の動作周波数(MHz)
  5557:       //double currentMHz = mpuCurrentMHz;
  5558:       if (mpuUtilOn) {  //目標の負荷率に近付ける
  5559:         //目標の負荷率(%)
  5560:         double targetPercent = Math.min (maxPercent, (double) mpuUtilRatio);
  5561:         mpuSetClockMHz ((1.2 - 0.2 * actualPercent / targetPercent) * mpuCurrentMHz);
  5562:       } else {  //目標の周波数に近づける
  5563:         mpuSetClockMHz (Math.min (maxPercent / actualPercent,
  5564:                                   1.2 - 0.2 * mpuCurrentMHz / mpuClockMHz) * mpuCurrentMHz);
  5565:       }
  5566:       Indicator.indUpdate (actualPercent);
  5567:       mpuAdjustmentCounter = MPU_ADJUSTMENT_INTERVAL;
  5568:     }
  5569:   }
  5570: 
  5571:   //mpuStop (message)
  5572:   //  コアのタスクが動いているとき、それを止める
  5573:   //  完全に止まってからデバッグダイアログを更新する
  5574:   public static void mpuStop (String message) {
  5575:     //トレース実行とステップ実行を中止する
  5576:     mpuAdvanceCount = 0;
  5577:     mpuStepCount = 0;
  5578:     mpuContinue = false;
  5579:     mpuStop1 (message);
  5580:   }  //mpuStop(String)
  5581:   public static void mpuStop1 (String message) {
  5582:     if (mpuTask == null) {  //既に停止しているか停止処理が始まっている
  5583:       return;
  5584:     }
  5585:     DisassembleList.ddpStoppedBy = message;  //停止理由
  5586:     mpuClockLimit = 0L;
  5587:     System.out.println (Multilingual.mlnJapanese ?
  5588:                         "MPU を停止します" :
  5589:                         "MPU stops");
  5590:     mpuTask.cancel ();
  5591:     mpuTask = null;
  5592:     //ステップ実行を継続する
  5593:     if (mpuStepCount != 0 && mpuContinue) {
  5594:       if (mpuStepCount == -1 || --mpuStepCount != 0) {
  5595:         mpuStep (mpuStepCount);
  5596:         return;
  5597:       }
  5598:     }
  5599:     mpuAdvanceCount = 0;
  5600:     mpuStepCount = 0;
  5601:     mpuContinue = false;
  5602:     //動作中だけ有効なボタンを無効にする
  5603:     for (AbstractButton button : mpuButtonsRunning) {
  5604:       button.setEnabled (false);
  5605:     }
  5606:     tmrTimer.schedule (new TimerTask () {
  5607:       @Override public void run () {
  5608:         mpuUpdateWindow ();
  5609:       }
  5610:     }, TMR_DELAY);
  5611:   }  //mpuStop1(message)
  5612: 
  5613:   //mpuAdvance (n)
  5614:   //  n回トレース実行する。0回は不可
  5615:   //  1ターンで実行するのであまり大きな値を指定しないこと
  5616:   //  終わってからデバッグダイアログを更新する
  5617:   //  コアが止まっていないときは何もしない
  5618:   public static void mpuAdvance (int n) {
  5619:     if (mpuTask != null) {  //コアが止まっていない
  5620:       return;
  5621:     }
  5622:     mpuAdvanceCount = n;
  5623:     DisassembleList.ddpStoppedBy = null;
  5624:     mpuTask = new TimerTask () {
  5625:       @Override public void run () {
  5626:         mpuContinue = true;
  5627:         do {
  5628:           mpuClockLimit = mpuClockTime + 1L;
  5629:           mpuExecuteCore ();
  5630:         } while (mpuContinue && --mpuAdvanceCount != 0);
  5631:         mpuClockLimit = 0L;
  5632:         if (mpuTask != null) {  //最初の命令のエラーで停止したときnullになっている場合がある
  5633:           mpuTask.cancel ();
  5634:           mpuTask = null;
  5635:         }
  5636:         if (mpuStepCount != 0 && mpuContinue) {  //ステップ実行中に分岐命令を1命令実行して自然に終了した
  5637:           if (mpuStepCount == -1 || --mpuStepCount != 0) {
  5638:             mpuStep (mpuStepCount);
  5639:             return;
  5640:           }
  5641:         }
  5642:         mpuAdvanceCount = 0;
  5643:         mpuStepCount = 0;
  5644:         mpuContinue = false;
  5645:         mpuUpdateWindow ();
  5646:       }
  5647:     };
  5648:     tmrTimer.schedule (mpuTask, TMR_DELAY);
  5649:   }  //mpuAdvance(int)
  5650: 
  5651:   //mpuStep (n)
  5652:   //  n回ステップ実行する。0回は不可。-1はステップアンティルリターン
  5653:   //  次の命令が分岐命令のときはトレース実行と同じ
  5654:   //  次の命令が分岐命令でないときはその直後まで実行する
  5655:   //  コアが止まっていないときは何もしない
  5656:   public static void mpuStep (int n) {
  5657:     if (mpuTask != null) {  //コアが止まっていない
  5658:       return;
  5659:     }
  5660:     mpuStepCount = n;
  5661:     Disassembler.disDisassemble (new StringBuilder (), regPC, regSRS);
  5662:     if ((Disassembler.disStatus & (Disassembler.DIS_ALWAYS_BRANCH | Disassembler.DIS_SOMETIMES_BRANCH)) != 0) {
  5663:       if (mpuStepCount == -1 &&  //ステップアンティルリターン
  5664:           (Disassembler.disOC == 0x4e73 ||  //RTE
  5665:            Disassembler.disOC == 0x4e74 ||  //RTD
  5666:            Disassembler.disOC == 0x4e75 ||  //RTR
  5667:            Disassembler.disOC == 0x4e77) &&  //RTS
  5668:           mpuUntilReturnSRS == regSRS &&  //ユーザモード/スーパーバイザモードが同じ
  5669:           (currentMPU < Model.MPU_MC68LC040 ||
  5670:            mpuUntilReturnRP == (regSRS != 0 ? MC68060.mmuSRP : MC68060.mmuURP)) &&  //MC68060のときルートポインタが同じ
  5671:           mpuUntilReturnPC0 != regPC0 &&  //プログラムカウンタが違う
  5672:           Integer.compareUnsigned (mpuUntilReturnSP, regRn[15]) <= 0) {  //スタックポインタが減っていない
  5673:         mpuAdvanceCount = 0;
  5674:         mpuStepCount = 0;
  5675:         mpuContinue = false;
  5676:         mpuUpdateWindow ();
  5677:         return;
  5678:       }
  5679:       mpuAdvance (1);
  5680:     } else {
  5681:       if (InstructionBreakPoint.IBP_ON) {
  5682:         InstructionBreakPoint.ibpInstant (Disassembler.disPC, DisassembleList.ddpSupervisorMode);
  5683:         mpuStart ();
  5684:       }
  5685:     }
  5686:   }  //mpuStep(int)
  5687: 
  5688:   //mpuStepUntilReturn ()
  5689:   //  ステップアンティルリターン
  5690:   //  RTD,RTE,RTR,RTSを実行する直前で
  5691:   //    ステップアンティルリターン開始時と
  5692:   //      ユーザモード/スーパーバイザモードが同じ
  5693:   //      MC68060のときルートポインタが同じ
  5694:   //      プログラムカウンタが違う
  5695:   //      スタックポインタが減っていない
  5696:   //    ならば停止する
  5697:   //  コアが止まっていないときは何もしない
  5698:   public static void mpuStepUntilReturn () {
  5699:     if (mpuTask != null) {  //コアが止まっていない
  5700:       return;
  5701:     }
  5702:     mpuUntilReturnSRS = regSRS;
  5703:     mpuUntilReturnRP = regSRS != 0 ? MC68060.mmuSRP : MC68060.mmuURP;
  5704:     mpuUntilReturnPC0 = regPC0;
  5705:     mpuUntilReturnSP = regRn[15];
  5706:     mpuStep (-1);
  5707:   }  //mpuStepUntilReturn()
  5708: 
  5709:   //mpuUpdateWindow ()
  5710:   //  停止したときデバッグ関連ウインドウやボタンを更新する
  5711:   public static void mpuUpdateWindow () {
  5712:     if (dbgVisibleMask != 0) {  //デバッグ関連ウインドウが表示されている
  5713:       if ((dbgVisibleMask & DBG_DDP_VISIBLE_MASK) != 0) {
  5714:         DisassembleList.ddpBacktraceRecord = -1L;  //分岐レコードの選択を解除する
  5715:         DisassembleList.ddpUpdate (-1, -1, false);
  5716:       }
  5717:       if (BranchLog.BLG_ON) {
  5718:         if ((dbgVisibleMask & DBG_BLG_VISIBLE_MASK) != 0) {
  5719:           BranchLog.blgUpdate (BranchLog.BLG_SELECT_NEWEST);
  5720:         }
  5721:       }
  5722:       if (ProgramFlowVisualizer.PFV_ON) {
  5723:         if ((dbgVisibleMask & DBG_PFV_VISIBLE_MASK) != 0) {
  5724:           ProgramFlowVisualizer.pfvUpdate ();
  5725:         }
  5726:       }
  5727:       if (RasterBreakPoint.RBP_ON) {
  5728:         if ((dbgVisibleMask & DBG_RBP_VISIBLE_MASK) != 0) {
  5729:           RasterBreakPoint.rbpUpdateFrame ();
  5730:         }
  5731:       }
  5732:       if (ScreenModeTest.SMT_ON) {
  5733:         if ((dbgVisibleMask & DBG_SMT_VISIBLE_MASK) != 0) {
  5734:           ScreenModeTest.smtUpdateFrame ();
  5735:         }
  5736:       }
  5737:       if (RootPointerList.RTL_ON) {
  5738:         if ((dbgVisibleMask & DBG_RTL_VISIBLE_MASK) != 0) {
  5739:           RootPointerList.rtlUpdateFrame ();
  5740:         }
  5741:       }
  5742:       if (SpritePatternViewer.SPV_ON) {
  5743:         if ((dbgVisibleMask & DBG_SPV_VISIBLE_MASK) != 0) {
  5744:           SpritePatternViewer.spvUpdateFrame ();
  5745:         }
  5746:       }
  5747:       if (ATCMonitor.ACM_ON) {
  5748:         if ((dbgVisibleMask & DBG_ACM_VISIBLE_MASK) != 0) {
  5749:           ATCMonitor.acmUpdateFrame ();
  5750:         }
  5751:       }
  5752:     }
  5753:     //コンソールにレジスタ一覧を表示する
  5754:     if (DebugConsole.dgtRequestRegs) {
  5755:       ExpressionEvaluator.ElementType.ETY_COMMAND_REGS.etyEval (null, ExpressionEvaluator.EVM_COMMAND);
  5756:       DebugConsole.dgtRequestRegs = false;
  5757:       DebugConsole.dgtPrintPrompt ();
  5758:     }
  5759:     //動作中だけ有効なボタンを無効にする
  5760:     for (AbstractButton button : mpuButtonsRunning) {
  5761:       button.setEnabled (false);
  5762:     }
  5763:     //停止中だけ有効なボタンを有効にする
  5764:     for (AbstractButton button : mpuButtonsStopped) {
  5765:       button.setEnabled (true);
  5766:     }
  5767:   }  //mpuUpdateWindow()
  5768: 
  5769:   //button = mpuMakeBreakButton ()
  5770:   //  停止ボタンを作る
  5771:   public static JButton mpuMakeBreakButton () {
  5772:     return mpuAddButtonRunning (
  5773:       Multilingual.mlnToolTipText (
  5774:         ComponentFactory.createImageButton (
  5775:           LnF.LNF_BREAK_IMAGE,
  5776:           LnF.LNF_BREAK_DISABLED_IMAGE,
  5777:           "Stop", mpuDebugActionListener),
  5778:         "ja", "停止")
  5779:       );
  5780:   }  //mpuMakeBreakButton()
  5781: 
  5782:   //button = mpuMakeTraceButton ()
  5783:   //  トレース実行ボタンを作る
  5784:   public static JButton mpuMakeTraceButton () {
  5785:     return mpuAddButtonStopped (
  5786:       Multilingual.mlnToolTipText (
  5787:         ComponentFactory.createImageButton (
  5788:           LnF.LNF_TRACE_IMAGE,
  5789:           LnF.LNF_TRACE_DISABLED_IMAGE,
  5790:           "Trace", mpuDebugActionListener),
  5791:         "ja", "トレース")
  5792:       );
  5793:   }  //mpuMakeTraceButton()
  5794: 
  5795:   //button = mpuMakeTrace10Button ()
  5796:   //  トレース10回ボタンを作る
  5797:   public static JButton mpuMakeTrace10Button () {
  5798:     return mpuAddButtonStopped (
  5799:       Multilingual.mlnToolTipText (
  5800:         ComponentFactory.createImageButton (
  5801:           LnF.LNF_TRACE_10_IMAGE,
  5802:           LnF.LNF_TRACE_10_DISABLED_IMAGE,
  5803:           "Trace 10 times", mpuDebugActionListener),
  5804:         "ja", "トレース 10 回")
  5805:       );
  5806:   }  //mpuMakeTrace10Button()
  5807: 
  5808:   //button = mpuMakeTrace100Button ()
  5809:   //  トレース100回ボタンを作る
  5810:   public static JButton mpuMakeTrace100Button () {
  5811:     return mpuAddButtonStopped (
  5812:       Multilingual.mlnToolTipText (
  5813:         ComponentFactory.createImageButton (
  5814:           LnF.LNF_TRACE_100_IMAGE,
  5815:           LnF.LNF_TRACE_100_DISABLED_IMAGE,
  5816:           "Trace 100 times", mpuDebugActionListener),
  5817:         "ja", "トレース 100 回")
  5818:       );
  5819:   }  //mpuMakeTrace100Button()
  5820: 
  5821:   //button = mpuMakeStepButton ()
  5822:   //  ステップ実行ボタンを作る
  5823:   public static JButton mpuMakeStepButton () {
  5824:     return mpuAddButtonStopped (
  5825:       Multilingual.mlnToolTipText (
  5826:         ComponentFactory.createImageButton (
  5827:           LnF.LNF_STEP_IMAGE,
  5828:           LnF.LNF_STEP_DISABLED_IMAGE,
  5829:           "Step", mpuDebugActionListener),
  5830:         "ja", "ステップ")
  5831:       );
  5832:   }  //mpuMakeStepButton()
  5833: 
  5834:   //button = mpuMakeStep10Button ()
  5835:   //  ステップ10回ボタンを作る
  5836:   public static JButton mpuMakeStep10Button () {
  5837:     return mpuAddButtonStopped (
  5838:       Multilingual.mlnToolTipText (
  5839:         ComponentFactory.createImageButton (
  5840:           LnF.LNF_STEP_10_IMAGE,
  5841:           LnF.LNF_STEP_10_DISABLED_IMAGE,
  5842:           "Step 10 times", mpuDebugActionListener),
  5843:         "ja", "ステップ 10 回")
  5844:       );
  5845:   }  //mpuMakeStep10Button()
  5846: 
  5847:   //button = mpuMakeStep100Button ()
  5848:   //  ステップ100回ボタンを作る
  5849:   public static JButton mpuMakeStep100Button () {
  5850:     return mpuAddButtonStopped (
  5851:       Multilingual.mlnToolTipText (
  5852:         ComponentFactory.createImageButton (
  5853:           LnF.LNF_STEP_100_IMAGE,
  5854:           LnF.LNF_STEP_100_DISABLED_IMAGE,
  5855:           "Step 100 times", mpuDebugActionListener),
  5856:         "ja", "ステップ 100 回")
  5857:       );
  5858:   }  //mpuMakeStep100Button()
  5859: 
  5860:   //button = mpuMakeReturnButton ()
  5861:   //  ステップアンティルリターンボタンを作る
  5862:   public static JButton mpuMakeReturnButton () {
  5863:     return mpuAddButtonStopped (
  5864:       Multilingual.mlnToolTipText (
  5865:         ComponentFactory.createImageButton (
  5866:           LnF.LNF_STEP_UNTIL_RETURN_IMAGE,
  5867:           LnF.LNF_STEP_UNTIL_RETURN_DISABLED_IMAGE,
  5868:           "Step until return", mpuDebugActionListener),
  5869:         "ja", "ステップアンティルリターン")
  5870:       );
  5871:   }  //mpuMakeReturnButton()
  5872: 
  5873:   //button = mpuMakeRunButton ()
  5874:   //  実行ボタンを作る
  5875:   public static JButton mpuMakeRunButton () {
  5876:     return mpuAddButtonStopped (
  5877:       Multilingual.mlnToolTipText (
  5878:         ComponentFactory.createImageButton (
  5879:           LnF.LNF_RUN_IMAGE,
  5880:           LnF.LNF_RUN_DISABLED_IMAGE,
  5881:           "Run", mpuDebugActionListener),
  5882:         "ja", "実行")
  5883:       );
  5884:   }  //mpuMakeRunButton()
  5885: 
  5886:   //button = mpuAddButtonRunning (button)
  5887:   //  MPUが動作中のときだけ有効なボタンを追加する
  5888:   public static <T extends AbstractButton> T mpuAddButtonRunning (T button) {
  5889:     button.setEnabled (mpuTask != null);
  5890:     mpuButtonsRunning.add (button);
  5891:     return button;
  5892:   }
  5893: 
  5894:   //button = mpuAddButtonStopped (button)
  5895:   //  MPUが停止中のときだけ有効なボタンを追加する
  5896:   public static <T extends AbstractButton> T mpuAddButtonStopped (T button) {
  5897:     button.setEnabled (mpuTask == null);
  5898:     mpuButtonsStopped.add (button);
  5899:     return button;
  5900:   }
  5901: 
  5902: 
  5903: 
  5904:   //========================================================================================
  5905:   //$$EMX エミュレータ拡張命令
  5906:   //  下位6bitの組み合わせで64個まで追加できる
  5907:   //  オペコードが変更される場合があるので原則としてユーザは使用禁止
  5908:   //  オペコード開始位置の上位10bitを変更するときはジャンプテーブルも修正すること
  5909:   //
  5910:   //  WAIT命令
  5911:   //    現在の割り込みマスクレベルで割り込みを受け付ける以外に何もしない
  5912:   //    やっていることはBRA *相当の無限ループだが、分岐ログは変化しない
  5913:   //    1回あたりの所要時間はMPUの種類や動作周波数に関係なく0.01msとする
  5914:   //    ホストのファイルにアクセスするといった時間のかかる処理を行うとき、
  5915:   //    コアを止めてしまうと本来ならば割り込みを用いて続けられる音楽やアニメーションが止まってしまうので、
  5916:   //    時間のかかる処理は別スレッドで行い、それが終わるまでコアはWAIT命令を繰り返して待つ
  5917:   public static final int EMX_OPCODE_BASE    = 0x4e00;  //オペコード開始位置
  5918:   public static final int EMX_OPCODE_HFSBOOT = EMX_OPCODE_BASE + 0x00;
  5919:   public static final int EMX_OPCODE_HFSINST = EMX_OPCODE_BASE + 0x01;
  5920:   public static final int EMX_OPCODE_HFSSTR  = EMX_OPCODE_BASE + 0x02;
  5921:   public static final int EMX_OPCODE_HFSINT  = EMX_OPCODE_BASE + 0x03;
  5922:   public static final int EMX_OPCODE_EMXNOP  = EMX_OPCODE_BASE + 0x04;
  5923:   public static final int EMX_OPCODE_EMXWAIT = EMX_OPCODE_BASE + 0x05;
  5924: 
  5925:   public static final String[] EMX_MNEMONIC_ARRAY = {
  5926:     "hfsboot",
  5927:     "hfsinst",
  5928:     "hfsstr",
  5929:     "hfsint",
  5930:     "emxnop",
  5931:     "emxwait",
  5932:   };
  5933: 
  5934:   //emxNop ()
  5935:   //  命令としては何もしない
  5936:   //  コードに埋め込んでパッチをあてたりするのに使う
  5937:   public static void emxNop () {
  5938:     if (MainMemory.mmrHumanVersion == 0x0302 && regPC0 == 0x00007140) {  //デバイスドライバを初期化する直前
  5939:       int head = regRn[9];  //初期化するデバイスドライバのデバイスヘッダのアドレス
  5940:       int tail = MC68060.mmuPeekLongData (0x00001c00, 1);  //デバイスドライバが使える末尾のアドレス
  5941:       //----------------------------------------------------------------
  5942:       //PCM8Aにパッチをあてる
  5943:       emxPatchPCM8A (head, tail);
  5944:       //----------------------------------------------------------------
  5945:       //RSDRV.SYS 2.02の先頭アドレスを保存する
  5946:       emxCheckRSDRV202 (head, tail);
  5947:     } else if (MainMemory.mmrHumanVersion == 0x0302 && regPC0 == 0x0000716c) {  //デバイスドライバを初期化した直後
  5948:       int head = regRn[9];  //初期化されたデバイスドライバのデバイスヘッダのアドレス
  5949:       int tail = MC68060.mmuPeekLongData (0x00001c00, 1);  //デバイスドライバが使える末尾のアドレス
  5950:       //----------------------------------------------------------------
  5951:       //060turbo.sysにパッチをあてる
  5952:       emxPatch060turbosys (head, tail);
  5953:       //----------------------------------------------------------------
  5954:       //FSX.Xのマウス受信データ処理ルーチンとマウスワークのアドレスを保存する
  5955:       if (Z8530.SCC_FSX_MOUSE) {
  5956:         emxCheckFSX (head, tail);
  5957:       }
  5958:       //----------------------------------------------------------------
  5959:       //TwentyOne.xのオプションのアドレスを保存する
  5960:       if (HFS.HFS_USE_TWENTY_ONE) {
  5961:         emxCheckTwentyOne (head, tail);
  5962:       }
  5963:       //----------------------------------------------------------------
  5964:       //ラベルをクリアする
  5965:       LabeledAddress.lblClear ();
  5966:     } else if (MainMemory.mmrHumanVersion == 0x0302 && regPC0 == 0x0000972c) {  //プロセスを起動する直前
  5967:       int head = regRn[8] + 256;  //起動するプロセスのメモリ管理テーブルのアドレス+256=プロセスの先頭
  5968:       //int tail = regRn[9];  //bssの末尾
  5969:       int tail = MC68060.mmuPeekLong (head - 208, 1);  //bssの先頭
  5970:       //----------------------------------------------------------------
  5971:       //bsio.x 0.21の先頭アドレスを保存する
  5972:       emxCheckBSIO021 (head, tail);
  5973:       //----------------------------------------------------------------
  5974:       //PCM8Aにパッチをあてる
  5975:       emxPatchPCM8A (head, tail);
  5976:       //----------------------------------------------------------------
  5977:       //tmsio.x 0.31の先頭アドレスを保存する
  5978:       emxCheckTMSIO031 (head, tail);
  5979:       //----------------------------------------------------------------
  5980:       //ラベルをクリアする
  5981:       LabeledAddress.lblClear ();
  5982:       //----------------------------------------------------------------
  5983:       //実行開始位置で停止する
  5984:       if (dbgStopAtStart) {
  5985:         InstructionBreakPoint.ibpInstant (regRn[12], 0);  //a4
  5986:       }
  5987:     } else if (MainMemory.mmrHumanVersion == 0x0302 && regPC0 == 0x0000a090) {  //プロセスが常駐した直後
  5988:       int head = regRn[8] + 256;  //常駐したプロセスのメモリ管理テーブルのアドレス+256=プロセスの先頭
  5989:       int tail = MC68060.mmuPeekLongData (regRn[8] + 8, 1);  //メモリブロックが使用している末尾
  5990:       String name = MC68060.mmuPeekStringZ (head - 60, 1);  //実行ファイル名
  5991:       if (name.equalsIgnoreCase ("fsx.x")) {
  5992:         //----------------------------------------------------------------
  5993:         //FSX.Xのマウス受信データ処理ルーチンとマウスワークのアドレスを保存する
  5994:         if (Z8530.SCC_FSX_MOUSE) {
  5995:           emxCheckFSX (head, tail);
  5996:         }
  5997:       }
  5998:       if (name.equalsIgnoreCase ("TwentyOne.x")) {
  5999:         //----------------------------------------------------------------
  6000:         //TwentyOne.xのオプションのアドレスを保存する
  6001:         if (HFS.HFS_USE_TWENTY_ONE) {
  6002:           emxCheckTwentyOne (head, tail);
  6003:         }
  6004:       }
  6005:     }
  6006:   }  //emxNop()
  6007: 
  6008:   public static final int[] emxPCM8AFFMap = {
  6009:     0x00000138, 0x000001f6, 0x00000394, 0x000011ec, 0x0000120a, 0x00001400, 0x00001814, 0x00001870, 0x00001882, 0x0000188a,
  6010:     0x00001892, 0x000018a2, 0x000018a8, 0x000018ca, 0x000018d4, 0x000018e0, 0x000018e8, 0x00001908, 0x000019e4, 0x00001afa,
  6011:     0x00001b58, 0x00001b7c, 0x00001bac, 0x00001c38, 0x00001ccc, 0x000021f8, 0x00002250, 0x00002258, 0x00002290, 0x000022a6,
  6012:     0x000022b0, 0x000022c0, 0x000022c8, 0x000022de, 0x000022ea, 0x000030c8, 0x000030de, 0x000030e6, 0x000030ea, 0x000030f6,
  6013:     0x00003112, 0x00003188, 0x0000334c, 0x0000338a, 0x000033a2, 0x000033c4, 0x000033d0, 0x0000341a, 0x00003428, 0x00003496,
  6014:     0x000034a6, 0x000034d6, 0x0000fe0e, 0x0000fec8, 0x0000feec, 0x0000ff46, 0x0000ff4e,
  6015:   };
  6016: 
  6017:   //emxPatchPCM8A (head, tail)
  6018:   //  headから始まるデバイスドライバまたはプロセスがPCM8A.X v1.02ならばパッチをあてる
  6019:   public static void emxPatchPCM8A (int head, int tail) {
  6020:     if (head + 0x0000ff60 <= tail &&
  6021:         MC68060.mmuPeekLongData (head + 0x10f8, 1) == 0x50434d38 &&  //PCM8
  6022:         MC68060.mmuPeekLongData (head + 0x10fc, 1) == 0x41313032) {  //A102
  6023:       System.out.println (Multilingual.mlnJapanese ?
  6024:                           "PCM8A.X 1.02 があります" :
  6025:                           "PCM8A.X 1.02 exists");
  6026:       int patched = 0;
  6027:       int failed = 0;
  6028:       //  I/Oポートのアドレスの上位8ビットが$FFになっているところを$00に修正します。(57箇所)
  6029:       for (int offset : emxPCM8AFFMap) {
  6030:         if (MC68060.mmuPeekByteZeroData (head + offset, 1) == 0xff) {
  6031:           MC68060.mmuPokeByteData (head + offset, 0x00, 1);
  6032:           patched++;
  6033:         } else {
  6034:           failed++;
  6035:         }
  6036:       }
  6037:       if (patched != 0) {
  6038:         System.out.printf (Multilingual.mlnJapanese ?
  6039:                            "PCM8A.X 1.02 にパッチをあてました (%d/%d)\n" :
  6040:                            "PCM8A.X 1.02 was patched (%d/%d)\n",
  6041:                            patched, patched + failed);
  6042:       }
  6043:     }
  6044:   }  //emxPatchPCM8A
  6045: 
  6046:   //emxPatch060turbosys (head, tail)
  6047:   //  060turbo.sysにパッチをあてる
  6048:   public static void emxPatch060turbosys (int head, int tail) {
  6049:     //  sysStat_8000::
  6050:     //  00000EC0  203C302E3536  move.l  #'0.56',d0
  6051:     //  00000EC6  227C30363054  movea.l #'060T',a1
  6052:     //  00000ECC  4E75          rts
  6053:     if (head + 0x00002000 <= tail &&
  6054:         MC68060.mmuPeekLongData (head + 0x00000ec0, 1) == 0x203c302e &&
  6055:         MC68060.mmuPeekLongData (head + 0x00000ec4, 1) == 0x3536227c &&
  6056:         MC68060.mmuPeekLongData (head + 0x00000ec8, 1) == 0x30363054) {  //060turbo.sys version 0.56
  6057:       System.out.println (Multilingual.mlnJapanese ?
  6058:                           "060turbo.sys 0.56 があります" :
  6059:                           "060turbo.sys 0.56 exists");
  6060:       //SCSIコールでバスエラーが出ることがある
  6061:       //  SRAMのソフト転送フラグを確認する命令がbtstではなくbsetになっている
  6062:       //  000021E6  08F9000400ED0070  bset.b  #4,$00ED0070  →  000021E6  0839000400ED0070  btst.b  #4,$00ED0070
  6063:       int patched = 0;
  6064:       int failed = 0;
  6065:       if (MC68060.mmuPeekLongData (head + 0x000021e6, 1) == 0x08f90004 &&
  6066:           MC68060.mmuPeekLongData (head + 0x000021ea, 1) == 0x00ed0070) {
  6067:         MC68060.mmuPokeWordData (head + 0x000021e6, 0x0839, 1);
  6068:         patched++;
  6069:       } else {
  6070:         failed++;
  6071:       }
  6072:       System.out.printf (Multilingual.mlnJapanese ?
  6073:                          "060turbo.sys 0.56 にパッチをあてました (%d/%d)\n" :
  6074:                          "060turbo.sys 0.56 was patched (%d/%d)\n",
  6075:                          patched, patched + failed);
  6076:     }
  6077:   }  //emxPatch060turbosys
  6078: 
  6079:   //emxCheckFSX (head, tail)
  6080:   //  headから始まるデバイスドライバまたはプロセスがFSX.Xならばマウス受信データ処理ルーチンとマウスワークのアドレスを保存する
  6081:   public static void emxCheckFSX (int head, int tail) {
  6082:     if (Z8530.SCC_FSX_MOUSE) {
  6083:       if (head + 0x00063200 <= tail &&
  6084:           "\r\nSX SYSTEM for X68000  version 3.10\r\nCopyright 1990,91,92,93,94 SHARP/First Class Technology\r\n".equals (MC68060.mmuPeekStringZ (head + 0x0001ae, 5))) {
  6085:         System.out.println (Multilingual.mlnJapanese ?
  6086:                             "FSX.X 3.10 があります" :
  6087:                             "FSX.X 3.10 exists");
  6088:         Z8530.sccFSXMouseHook = head + 0x04f82a;  //マウス受信データ処理ルーチン
  6089:         Z8530.sccFSXMouseWork = head + 0x063184;  //マウスワーク
  6090:       }
  6091:     }
  6092:   }  //emxCheckFSX
  6093: 
  6094:   //emxCheckRSDRV202 (head, tail)
  6095:   //  RSDRV.SYS 2.02の先頭アドレスを保存する
  6096:   //  あるからといって使われているとは限らない
  6097:   //  タイトル部分はバッファになるので実行前に呼び出すこと
  6098:   //  ボーレート11=76800bpsを指定できるようにパッチをあてる
  6099:   public static void emxCheckRSDRV202 (int head, int tail) {
  6100:     if (head + 0x000ea6 <= tail &&
  6101:         MC68060.mmuPeekEquals (head + 0x000e4e, "RS-232C DRIVER for X68000 version 2.02")) {
  6102:       if (RS232CTerminal.trmRSDRV202Head != head) {
  6103:         RS232CTerminal.trmRSDRV202Head = head;
  6104:         int[] patchData = {
  6105:           //                                 変更前                         変更後
  6106:           //                           05F6  B03C  cmp.b   #10,d0           B03C  cmp.b   #11,d0
  6107:           0x05f8, 0x000a, 0x000b,  //  05F8  000A                           000B
  6108:           //
  6109:           0x0600, 0xd040, 0x2048,  //  0600  D040  add.w   d0,d0            2048  movea.l a0,a0
  6110:           //
  6111:           0x060e, 0x3030, 0x4e90,  //  060E  3030  move.w  $00(a0,d0.w),d0  4E90  jsr     (a0)
  6112:           0x0610, 0x0000, 0x2048,  //  0610  0000                           2048  movea.l a0,a0
  6113:           //
  6114:           0x074e, 0x0821, 0x2041,  //  074E  0821  .dc.w   2081             2041  movea.l d1,a0
  6115:           0x0750, 0x0410, 0x3200,  //  0750  0410  .dc.w   1040             3200  move.w  d0,d1
  6116:           0x0752, 0x0207, 0x303c,  //  0752  0207  .dc.w   519              303C  move.w  #2083,d0
  6117:           0x0754, 0x0102, 0x0823,  //  0754  0102  .dc.w   258              0823
  6118:           0x0756, 0x0080, 0xe268,  //  0756  0080  .dc.w   128              E268  lsr.w   d1,d0
  6119:           0x0758, 0x003f, 0x72fe,  //  0758  003F  .dc.w   63               72FE  moveq.l #-2,d1
  6120:           0x075a, 0x001f, 0xd141,  //  075A  001F  .dc.w   31               D141  addx.w  d1,d0
  6121:           0x075c, 0x000e, 0x2208,  //  075C  000E  .dc.w   14               2208  move.l  a0,d1
  6122:           0x075e, 0x0006, 0x4e75,  //  075E  0006  .dc.w   6                4E75  rts
  6123:           //                           0760  0002  .dc.w   2
  6124:           //
  6125:           0x0ab0, 0x0040, 0x0400,  //  0AB0  0040  .dc.w   64               0400  .dc.w   1024
  6126:           0x0ad2, 0x0040, 0x0400,  //  0AD2  0040  .dc.w   64               0400  .dc.w   1024
  6127:           0x0af4, 0x0040, 0x0400,  //  0AF4  0040  .dc.w   64               0400  .dc.w   1024
  6128:           0x0b16, 0x0040, 0x0400,  //  0B16  0040  .dc.w   64               0400  .dc.w   1024
  6129:           0x0b38, 0x0040, 0x0400,  //  0B38  0040  .dc.w   64               0400  .dc.w   1024
  6130:           //
  6131:           //                           0CAC  B23C  cmp.b   #9,d1            B23C  cmp.b   #11,d1
  6132:           0x0cae, 0x0009, 0x000b,  //  0CAE  0009                           000B
  6133:         };
  6134:         int patched = 0;
  6135:         int failed = 0;
  6136:         for (int i = 0; i < patchData.length; i += 3) {
  6137:           int a = head + patchData[i];
  6138:           int b = patchData[i + 1];
  6139:           int c = patchData[i + 2];
  6140:           int d = MC68060.mmuPeekWordZeroData (a, 1);
  6141:           if (d == b) {
  6142:             MC68060.mmuPokeWordData (a, c, 1);
  6143:             patched++;
  6144:           } else if (d != c) {
  6145:             failed++;
  6146:           }
  6147:         }
  6148:         System.out.printf ("RSDRV.SYS 2.02 found at %08X and patched (%d/%d)\n", head, patched, patched + failed);
  6149:       }
  6150:     }
  6151:   }
  6152: 
  6153:   //emxCheckTMSIO031 (head, tail)
  6154:   //  tmsio.x 0.31の先頭アドレスを保存する
  6155:   //  あるからといって使われているとは限らない
  6156:   //  タイトル部分はバッファになるので実行前に呼び出すこと
  6157:   public static void emxCheckTMSIO031 (int head, int tail) {
  6158:     if (head + 0x000fc4 <= tail &&
  6159:         MC68060.mmuPeekEquals (head + 0x000d1c, "TMSIO version 0.31 Copyright (C) 1990-93 by Miki Hoshino")) {
  6160:       if (RS232CTerminal.trmTMSIO031Head != head) {
  6161:         RS232CTerminal.trmTMSIO031Head = head;
  6162:         System.out.printf ("TMSIO 0.31 found at %08X\n", head);
  6163:       }
  6164:     }
  6165:   }
  6166: 
  6167:   //emxCheckBSIO021 (head, tail)
  6168:   //  bsio.x 0.21の先頭アドレスを保存する
  6169:   //  あるからといって使われているとは限らない
  6170:   //  タイトル部分はバッファになるので実行前に呼び出すこと
  6171:   public static void emxCheckBSIO021 (int head, int tail) {
  6172:     if (head + 0x001c2c <= tail &&
  6173:         MC68060.mmuPeekEquals (head + 0x001a66, "BSIO  version 0.21 Copyright (C) 1994    By BAZU")) {
  6174:       if (RS232CTerminal.trmBSIO021Head != head) {
  6175:         RS232CTerminal.trmBSIO021Head = head;
  6176:         System.out.printf ("BSIO 0.21 found at %08X\n", head);
  6177:       }
  6178:     }
  6179:   }
  6180: 
  6181:   //emxCheckTwentyOne (head, tail)
  6182:   //  headから始まるデバイスドライバまたはプロセスがTwentyOne.xならばオプションのアドレスを保存する
  6183:   public static void emxCheckTwentyOne (int head, int tail) {
  6184:     if (HFS.HFS_USE_TWENTY_ONE &&
  6185:         head + 64 <= tail) {
  6186:       if (MainMemory.mmrTwentyOneOptionAddress != 0 ||  //TwentyOne.xのオプションのアドレスは確認済みまたは非対応のバージョン
  6187:           MainMemory.mmrHumanVersion <= 0) {  //Human68kのバージョンが未確認または未知のバージョン
  6188:         return;
  6189:       }
  6190:       int name1 = MC68060.mmuPeekLongData (head + 14, 1);
  6191:       if (name1 == ('*' << 24 | 'T' << 16 | 'w' << 8 | 'e')) {
  6192:         int name2 = MC68060.mmuPeekLongData (head + 18, 1);
  6193:         if (name2 == ('n' << 24 | 't' << 16 | 'y' << 8 | '*')) {  //TwentyOne.x v1.10まで
  6194:           MainMemory.mmrTwentyOneOptionAddress = -1;  //非対応
  6195:         }
  6196:       } else if (name1 == ('?' << 24 | 'T' << 16 | 'w' << 8 | 'e')) {
  6197:         int name2 = MC68060.mmuPeekLongData (head + 18, 1);
  6198:         if (name2 == ('n' << 24 | 't' << 16 | 'y' << 8 | '?') ||
  6199:             name2 == ('n' << 24 | 't' << 16 | 'y' << 8 | 'E')) {  //TwentyOne.x v1.11から
  6200:           System.out.println (Multilingual.mlnJapanese ?
  6201:                               "TwentyOne.x があります" :
  6202:                               "TwentyOne.x exists");
  6203:           MainMemory.mmrTwentyOneOptionAddress = head + 22;
  6204:         }
  6205:       }
  6206:     }
  6207:   }  //emxCheckTwentyOne
  6208: 
  6209: 
  6210: 
  6211:   //========================================================================================
  6212:   //$$IRP 命令の処理
  6213:   //
  6214:   //  変数名
  6215:   //    op                                   オペコード。iiii_qqq_nnn_mmm_rrr
  6216:   //    iiii  op >> 12                       命令の種類。ここでは定数
  6217:   //    qqq   (op >> 9) - (iiii << 3)        クイックイミディエイトまたはデータレジスタDqの番号
  6218:   //    aqq   (op >> 9) - ((iiii << 3) - 8)  アドレスレジスタAqの番号
  6219:   //    nnn   op >> 6 & 7                    デスティネーションの実効アドレスのモード
  6220:   //    ea    op & 63                        実効アドレスのモードとレジスタ
  6221:   //    mmm   ea >> 3                        実効アドレスのモード
  6222:   //    rrr   op & 7                         実効アドレスのレジスタ。DrまたはRrのときr[rrr]はr[ea]で代用できる
  6223:   //    cccc  op >> 8 & 15                   コンディションコード
  6224:   //    a                                    実効アドレス
  6225:   //    s                                    テンポラリ
  6226:   //    t                                    テンポラリ
  6227:   //    w                                    拡張ワード
  6228:   //    x                                    被演算数
  6229:   //    y                                    演算数
  6230:   //    z                                    結果
  6231:   //
  6232:   //  サイクル数
  6233:   //    mpuCycleCountにMC68000のサイクル数を加算する
  6234:   //      MC68030のサイクル数はMC68000のサイクル数の0.6倍とみなして計算する
  6235:   //      これはROM1.3で起動したときDBRA命令で計測される動作周波数の表示の辻褄を合わせるための係数であり、
  6236:   //      MC68000とMC68030のサイクル数の比の平均値ではない
  6237:   //        10MHzのMC68000と25MHzのMC68030の速度の比が25/10/0.6=4.17倍となるので何倍も外れてはいないと思われる
  6238:   //    MC68000に存在しない命令のサイクル数はMC68000に存在すると仮定した場合の推定値を用いる
  6239:   //      オペコードを含むリードとライトを1ワードあたり4サイクルとする
  6240:   //
  6241:   //  拡張命令
  6242:   //    差し障りのない範囲でいくつかの命令を追加してある
  6243:   //    エミュレータ拡張命令
  6244:   //      HFSBOOT                                         |-|012346|-|-----|-----|          |0100_111_000_000_000
  6245:   //      HFSINST                                         |-|012346|-|-----|-----|          |0100_111_000_000_001
  6246:   //      HFSSTR                                          |-|012346|-|-----|-----|          |0100_111_000_000_010
  6247:   //      HFSINT                                          |-|012346|-|-----|-----|          |0100_111_000_000_011
  6248:   //      EMXNOP                                          |-|012346|-|-----|-----|          |0100_111_000_000_100
  6249:   //    MC68000で欠番になっているオペコードに割り当てられているColdFireの命令
  6250:   //      BITREV.L Dr                                     |-|------|-|-----|-----|D         |0000_000_011_000_rrr (ISA_C)
  6251:   //      BYTEREV.L Dr                                    |-|------|-|-----|-----|D         |0000_001_011_000_rrr (ISA_C)
  6252:   //      FF1.L Dr                                        |-|------|-|-UUUU|-**00|D         |0000_010_011_000_rrr (ISA_C)
  6253:   //      MVS.B <ea>,Dq                                   |-|------|-|-UUUU|-**00|D M+-WXZPI|0111_qqq_100_mmm_rrr (ISA_B)
  6254:   //      MVS.W <ea>,Dq                                   |-|------|-|-UUUU|-**00|D M+-WXZPI|0111_qqq_101_mmm_rrr (ISA_B)
  6255:   //      MVZ.B <ea>,Dq                                   |-|------|-|-UUUU|-0*00|D M+-WXZPI|0111_qqq_110_mmm_rrr (ISA_B)
  6256:   //      MVZ.W <ea>,Dq                                   |-|------|-|-UUUU|-0*00|D M+-WXZPI|0111_qqq_111_mmm_rrr (ISA_B)
  6257:   //      SATS.L Dr                                       |-|------|-|-UUUU|-**00|D         |0100_110_010_000_rrr (ISA_B)
  6258: 
  6259:   public static final boolean IRP_BITREV_REVERSE = false;  //true=BITREVでInteger.reverseを使う
  6260:   public static final boolean IRP_BITREV_SHIFT = false;  //true=BITREVでシフト演算子を使う
  6261:   public static final boolean IRP_BITREV_TABLE = true;  //true=BITREVでテーブルを使う
  6262: 
  6263:   public static final boolean IRP_MOVEM_MAINMEMORY = true;  //true=000のときMOVEMでメインメモリを特別扱いにする
  6264:   public static final boolean IRP_MOVEM_EXPAND = false;  //true=MOVEMで16回展開する。遅くなる
  6265:   public static final boolean IRP_MOVEM_LOOP = false;  //true=MOVEMで16回ループする。コンパイラが展開する
  6266:   public static final boolean IRP_MOVEM_SHIFT_LEFT = false;  //true=MOVEMで0になるまで左にシフトする。reverseが入る分遅い
  6267:   public static final boolean IRP_MOVEM_SHIFT_RIGHT = true;  //true=MOVEMで0になるまで右にシフトする
  6268:   public static final boolean IRP_MOVEM_ZEROS = false;  //true=MOVEMでInteger.numberOfTrailingZerosを使う。ループ回数は少ないがスキップする処理が冗長になるので最速ではない
  6269: 
  6270:   //  リセット命令
  6271:   public static void irpReset () {
  6272:     //メインメモリのmmrResetとバスコントローラのbusResetはmpuResetへ
  6273:     CRTC.crtReset ();  //CRT CRTコントローラ
  6274:     VideoController.vcnReset ();  //VCN ビデオコントローラ
  6275:     HD63450.dmaReset ();  //DMA DMAコントローラ
  6276:     MC68901.mfpReset ();  //MFP MFP
  6277:     Keyboard.kbdReset ();  //KBD キーボード
  6278:     RP5C15.rtcReset ();  //RTC RTC
  6279:     PrinterPort.prnReset ();  //PRN プリンタポート
  6280:     SoundSource.sndReset ();  //SND サウンド
  6281:     OPM.opmReset ();  //OPM FM音源
  6282:     ADPCM.pcmReset ();  //PCM ADPCM音源
  6283:     FDC.fdcReset ();  //FDC FDコントローラ
  6284:     IOInterrupt.ioiReset ();  //IOI I/O割り込み
  6285:     eb2Reset ();  //EB2 拡張ボードレベル2割り込み
  6286:     SPC.spcReset ();  //SPC SCSIプロトコルコントローラ
  6287:     if (SUK.SUK_ON) {
  6288:       SUK.sukReset ();  //SUK すかじーU君改
  6289:     }
  6290:     Z8530.sccReset ();  //SCC SCC
  6291:     RS232CTerminal.trmReset ();  //TRM RS-232C設定とターミナル
  6292:     PPI.ppiReset ();  //PPI PPI
  6293:     HFS.hfsReset ();  //HFS ホストファイルシステムインタフェイス
  6294:     SpriteScreen.sprReset ();  //SPR スプライト画面
  6295:     //smrReset()はspcSCSIEXOnとspcSCSIINOnを使うのでSPC.spcReset()よりも後であること
  6296:     xt3Reset ();  //XT3 Xellent30
  6297:     SRAM.smrReset ();  //SMR SRAM
  6298:     CONDevice.conReset ();  //CON CONデバイス制御
  6299:   }  //irpReset()
  6300: 
  6301:   //右シフト・ローテート命令
  6302:   //
  6303:   //  ASR
  6304:   //    X  countが0のとき変化しない。他は最後に押し出されたビット
  6305:   //    N  結果の最上位ビット
  6306:   //    Z  結果が0のときセット。他はクリア
  6307:   //    V  常にクリア
  6308:   //    C  countが0のときクリア。他は最後に押し出されたビット
  6309:   //    ASR.B
  6310:   //         ........................アイウエオカキク X C
  6311:   //       0 ........................アイウエオカキク X 0
  6312:   //       1 ........................アアイウエオカキ ク ク
  6313:   //       :
  6314:   //       7 ........................アアアアアアアア イ イ
  6315:   //       8 ........................アアアアアアアア ア ア
  6316:   //    ASR.W
  6317:   //         ................アイウエオカキクケコサシスセソタ X C
  6318:   //       0 ................アイウエオカキクケコサシスセソタ X 0
  6319:   //       1 ................アアイウエオカキクケコサシスセソ タ タ
  6320:   //       :
  6321:   //      15 ................アアアアアアアアアアアアアアアア イ イ
  6322:   //      16 ................アアアアアアアアアアアアアアアア ア ア
  6323:   //    ASR.L
  6324:   //         アイウエオカキクケコサシスセソタチツテトナニヌネノハヒフヘホマミ X C
  6325:   //       0 アイウエオカキクケコサシスセソタチツテトナニヌネノハヒフヘホマミ X 0
  6326:   //       1 アアイウエオカキクケコサシスセソタチツテトナニヌネノハヒフヘホマ ミ ミ
  6327:   //       :
  6328:   //      31 アアアアアアアアアアアアアアアアアアアアアアアアアアアアアアアア イ イ
  6329:   //      32 アアアアアアアアアアアアアアアアアアアアアアアアアアアアアアアア ア ア
  6330:   //
  6331:   //  LSR
  6332:   //    X  countが0のとき変化しない。他は最後に押し出されたビット
  6333:   //    N  結果の最上位ビット
  6334:   //    Z  結果が0のときセット。他はクリア
  6335:   //    V  常にクリア
  6336:   //    C  countが0のときクリア。他は最後に押し出されたビット
  6337:   //    LSR.B
  6338:   //         ........................アイウエオカキク X C
  6339:   //       0 ........................アイウエオカキク X 0
  6340:   //       1 ........................0アイウエオカキ ク ク
  6341:   //       :
  6342:   //       7 ........................0000000ア イ イ
  6343:   //       8 ........................00000000 ア ア
  6344:   //       9 ........................00000000 0 0
  6345:   //    LSR.W
  6346:   //         ................アイウエオカキクケコサシスセソタ X C
  6347:   //       0 ................アイウエオカキクケコサシスセソタ X 0
  6348:   //       1 ................0アイウエオカキクケコサシスセソ タ タ
  6349:   //       :
  6350:   //      15 ................000000000000000ア イ イ
  6351:   //      16 ................0000000000000000 ア ア
  6352:   //      17 ................0000000000000000 0 0
  6353:   //    LSR.L
  6354:   //         アイウエオカキクケコサシスセソタチツテトナニヌネノハヒフヘホマミ X C
  6355:   //       0 アイウエオカキクケコサシスセソタチツテトナニヌネノハヒフヘホマミ X 0
  6356:   //       1 0アイウエオカキクケコサシスセソタチツテトナニヌネノハヒフヘホマ ミ ミ
  6357:   //       :
  6358:   //      31 0000000000000000000000000000000ア イ イ
  6359:   //      32 00000000000000000000000000000000 ア ア
  6360:   //      33 00000000000000000000000000000000 0 0
  6361:   //
  6362:   //  ROXR
  6363:   //    X  countが0のとき変化しない。他は最後に押し出されたビット
  6364:   //    N  結果の最上位ビット
  6365:   //    Z  結果が0のときセット。他はクリア
  6366:   //    V  常にクリア
  6367:   //    C  countが0のときXのコピー。他は最後に押し出されたビット
  6368:   //    ROXR.B
  6369:   //         ........................アイウエオカキク X C
  6370:   //       0 ........................アイウエオカキク X X
  6371:   //       1 ........................Xアイウエオカキ ク ク
  6372:   //       2 ........................クXアイウエオカ キ キ
  6373:   //       :
  6374:   //       7 ........................ウエオカキクXア イ イ
  6375:   //       8 ........................イウエオカキクX ア ア
  6376:   //       9 ........................アイウエオカキク X X
  6377:   //    ROXR.W
  6378:   //         ................アイウエオカキクケコサシスセソタ X C
  6379:   //       0 ................アイウエオカキクケコサシスセソタ X X
  6380:   //       1 ................Xアイウエオカキクケコサシスセソ タ タ
  6381:   //       2 ................タXアイウエオカキクケコサシスセ ソ ソ
  6382:   //       :
  6383:   //      15 ................ウエオカキクケコサシスセソタXア イ イ
  6384:   //      16 ................イウエオカキクケコサシスセソタX ア ア
  6385:   //      17 ................アイウエオカキクケコサシスセソタ X X
  6386:   //    ROXR.L
  6387:   //         アイウエオカキクケコサシスセソタチツテトナニヌネノハヒフヘホマミ X C
  6388:   //       0 アイウエオカキクケコサシスセソタチツテトナニヌネノハヒフヘホマミ X X
  6389:   //       1 Xアイウエオカキクケコサシスセソタチツテトナニヌネノハヒフヘホマ ミ ミ
  6390:   //       2 ミXアイウエオカキクケコサシスセソタチツテトナニヌネノハヒフヘホ マ マ
  6391:   //       :
  6392:   //      31 ウエオカキクケコサシスセソタチツテトナニヌネノハヒフヘホマミXア イ イ
  6393:   //      32 イウエオカキクケコサシスセソタチツテトナニヌネノハヒフヘホマミX ア ア
  6394:   //      33 アイウエオカキクケコサシスセソタチツテトナニヌネノハヒフヘホマミ X X
  6395:   //
  6396:   //  ROR
  6397:   //    X  常に変化しない
  6398:   //    N  結果の最上位ビット
  6399:   //    Z  結果が0のときセット。他はクリア
  6400:   //    V  常にクリア
  6401:   //    C  countが0のときクリア。他は結果の最上位ビット
  6402:   //    ROR.B
  6403:   //         ........................アイウエオカキク X C
  6404:   //       0 ........................アイウエオカキク X 0
  6405:   //       1 ........................クアイウエオカキ X ク
  6406:   //       :
  6407:   //       7 ........................イウエオカキクア X イ
  6408:   //       8 ........................アイウエオカキク X ア
  6409:   //    ROR.W
  6410:   //         ................アイウエオカキクケコサシスセソタ X C
  6411:   //       0 ................アイウエオカキクケコサシスセソタ X 0
  6412:   //       1 ................タアイウエオカキクケコサシスセソ X タ
  6413:   //       :
  6414:   //      15 ................イウエオカキクケコサシスセソタア X イ
  6415:   //      16 ................アイウエオカキクケコサシスセソタ X ア
  6416:   //    ROR.L
  6417:   //         アイウエオカキクケコサシスセソタチツテトナニヌネノハヒフヘホマミ X C
  6418:   //       0 アイウエオカキクケコサシスセソタチツテトナニヌネノハヒフヘホマミ X 0
  6419:   //       1 ミアイウエオカキクケコサシスセソタチツテトナニヌネノハヒフヘホマ X ミ
  6420:   //       :
  6421:   //      31 イウエオカキクケコサシスセソタチツテトナニヌネノハヒフヘホマミア X イ
  6422:   //      32 アイウエオカキクケコサシスセソタチツテトナニヌネノハヒフヘホマミ X ア
  6423: 
  6424:   //左シフト・ローテート命令
  6425:   //
  6426:   //  ASL
  6427:   //    X  countが0のとき変化しない。他は最後に押し出されたビット
  6428:   //    N  結果の最上位ビット
  6429:   //    Z  結果が0のときセット。他はクリア
  6430:   //    V  ASRで元に戻せないときセット。他はクリア
  6431:   //    C  countが0のときクリア。他は最後に押し出されたビット
  6432:   //    ASL.B
  6433:   //         ........................アイウエオカキク X C
  6434:   //       0 ........................アイウエオカキク X 0
  6435:   //       1 ........................イウエオカキク0 ア ア
  6436:   //       :
  6437:   //       7 ........................ク0000000 キ キ
  6438:   //       8 ........................00000000 ク ク
  6439:   //       9 ........................00000000 0 0
  6440:   //    ASL.W
  6441:   //         ................アイウエオカキクケコサシスセソタ X C
  6442:   //       0 ................アイウエオカキクケコサシスセソタ X 0
  6443:   //       1 ................イウエオカキクケコサシスセソタ0 ア ア
  6444:   //       :
  6445:   //      15 ................タ000000000000000 ソ ソ
  6446:   //      16 ................0000000000000000 タ タ
  6447:   //      17 ................0000000000000000 0 0
  6448:   //    ASL.L
  6449:   //         アイウエオカキクケコサシスセソタチツテトナニヌネノハヒフヘホマミ X C
  6450:   //       0 アイウエオカキクケコサシスセソタチツテトナニヌネノハヒフヘホマミ X 0
  6451:   //       1 イウエオカキクケコサシスセソタチツテトナニヌネノハヒフヘホマミ0 ア ア
  6452:   //       :
  6453:   //      31 ミ0000000000000000000000000000000 マ マ
  6454:   //      32 00000000000000000000000000000000 ミ ミ
  6455:   //      33 00000000000000000000000000000000 0 0
  6456:   //
  6457:   //  LSL
  6458:   //    X  countが0のとき変化しない。他は最後に押し出されたビット
  6459:   //    N  結果の最上位ビット
  6460:   //    Z  結果が0のときセット。他はクリア
  6461:   //    V  常にクリア
  6462:   //    C  countが0のときクリア。他は最後に押し出されたビット
  6463:   //    LSL.B
  6464:   //         ........................アイウエオカキク X C
  6465:   //       0 ........................アイウエオカキク X 0
  6466:   //       1 ........................イウエオカキク0 ア ア
  6467:   //       :
  6468:   //       7 ........................ク0000000 キ キ
  6469:   //       8 ........................00000000 ク ク
  6470:   //       9 ........................00000000 0 0
  6471:   //    LSL.W
  6472:   //         ................アイウエオカキクケコサシスセソタ X C
  6473:   //       0 ................アイウエオカキクケコサシスセソタ X 0
  6474:   //       1 ................イウエオカキクケコサシスセソタ0 ア ア
  6475:   //       :
  6476:   //      15 ................タ000000000000000 ソ ソ
  6477:   //      16 ................0000000000000000 タ タ
  6478:   //      17 ................0000000000000000 0 0
  6479:   //    LSL.L
  6480:   //         アイウエオカキクケコサシスセソタチツテトナニヌネノハヒフヘホマミ X C
  6481:   //       0 アイウエオカキクケコサシスセソタチツテトナニヌネノハヒフヘホマミ X 0
  6482:   //       1 イウエオカキクケコサシスセソタチツテトナニヌネノハヒフヘホマミ0 ア ア
  6483:   //       :
  6484:   //      31 ミ0000000000000000000000000000000 マ マ
  6485:   //      32 00000000000000000000000000000000 ミ ミ
  6486:   //      33 00000000000000000000000000000000 0 0
  6487:   //
  6488:   //  ROXL
  6489:   //    X  countが0のとき変化しない。他は最後に押し出されたビット
  6490:   //    N  結果の最上位ビット
  6491:   //    Z  結果が0のときセット。他はクリア
  6492:   //    V  常にクリア
  6493:   //    C  countが0のときXのコピー。他は最後に押し出されたビット
  6494:   //    ROXL.B
  6495:   //         ........................アイウエオカキク X C
  6496:   //       0 ........................アイウエオカキク X X
  6497:   //       1 ........................イウエオカキクX ア ア
  6498:   //       2 ........................ウエオカキクXア イ イ
  6499:   //       :
  6500:   //       7 ........................クXアイウエオカ キ キ
  6501:   //       8 ........................Xアイウエオカキ ク ク
  6502:   //       9 ........................アイウエオカキク X X
  6503:   //    ROXL.W
  6504:   //         ................アイウエオカキクケコサシスセソタ X C
  6505:   //       0 ................アイウエオカキクケコサシスセソタ X X
  6506:   //       1 ................イウエオカキクケコサシスセソタX ア ア
  6507:   //       2 ................ウエオカキクケコサシスセソタXア イ イ
  6508:   //       :
  6509:   //      15 ................タXアイウエオカキクケコサシスセ ソ ソ
  6510:   //      16 ................Xアイウエオカキクケコサシスセソ タ タ
  6511:   //      17 ................アイウエオカキクケコサシスセソタ X X
  6512:   //    ROXL.L
  6513:   //         アイウエオカキクケコサシスセソタチツテトナニヌネノハヒフヘホマミ X C
  6514:   //       0 アイウエオカキクケコサシスセソタチツテトナニヌネノハヒフヘホマミ X X
  6515:   //       1 イウエオカキクケコサシスセソタチツテトナニヌネノハヒフヘホマミX ア ア
  6516:   //       2 ウエオカキクケコサシスセソタチツテトナニヌネノハヒフヘホマミXア イ イ
  6517:   //       :
  6518:   //      31 ミXアイウエオカキクケコサシスセソタチツテトナニヌネノハヒフヘホ マ マ
  6519:   //      32 Xアイウエオカキクケコサシスセソタチツテトナニヌネノハヒフヘホマ ミ ミ
  6520:   //      33 アイウエオカキクケコサシスセソタチツテトナニヌネノハヒフヘホマミ X X
  6521:   //
  6522:   //  ROL
  6523:   //    X  常に変化しない
  6524:   //    N  結果の最上位ビット
  6525:   //    Z  結果が0のときセット。他はクリア
  6526:   //    V  常にクリア
  6527:   //    C  countが0のときクリア。他は結果の最下位ビット
  6528:   //    ROL.B
  6529:   //         ........................アイウエオカキク X C
  6530:   //       0 ........................アイウエオカキク X 0
  6531:   //       1 ........................イウエオカキクア X ア
  6532:   //       :
  6533:   //       7 ........................クアイウエオカキ X キ
  6534:   //       8 ........................アイウエオカキク X ク
  6535:   //    ROL.W
  6536:   //         ................アイウエオカキクケコサシスセソタ X C
  6537:   //       0 ................アイウエオカキクケコサシスセソタ X 0
  6538:   //       1 ................イウエオカキクケコサシスセソタア X ア
  6539:   //       :
  6540:   //      15 ................タアイウエオカキクケコサシスセソ X ソ
  6541:   //      16 ................アイウエオカキクケコサシスセソタ X タ
  6542:   //    ROL.L
  6543:   //         アイウエオカキクケコサシスセソタチツテトナニヌネノハヒフヘホマミ X C
  6544:   //       0 アイウエオカキクケコサシスセソタチツテトナニヌネノハヒフヘホマミ X 0
  6545:   //       1 イウエオカキクケコサシスセソタチツテトナニヌネノハヒフヘホマミア X ア
  6546:   //       :
  6547:   //      31 ミアイウエオカキクケコサシスセソタチツテトナニヌネノハヒフヘホマ X マ
  6548:   //      32 アイウエオカキクケコサシスセソタチツテトナニヌネノハヒフヘホマミ X ミ
  6549: 
  6550: 
  6551: 
  6552:   //========================================================================================
  6553:   //以下のメソッドはインライン展開する
  6554: /*
  6555:   public static void pushb (int x) throws M68kException {
  6556:     wb (r[15] -= 2, x);  //ワードの上位側
  6557:   }  //pushb(int)
  6558:   public static void pushw (int x) throws M68kException {
  6559:     ww (r[15] -= 2, x);
  6560:   }  //pushw(int)
  6561:   public static void pushl (int x) throws M68kException {
  6562:     wl (r[15] -= 4, x);
  6563:   }  //pushl(int)
  6564: 
  6565:   public static int popbs () throws M68kException {
  6566:     return rbs ((r[15] += 2) - 2);  //ワードの上位側
  6567:   }  //popbs()
  6568:   public static int popbz () throws M68kException {
  6569:     return rbz ((r[15] += 2) - 2);  //ワードの上位側
  6570:   }  //popbz()
  6571:   public static int popws () throws M68kException {
  6572:     return rws ((r[15] += 2) - 2);
  6573:   }  //popws()
  6574:   public static int popwz () throws M68kException {
  6575:     return rwz ((r[15] += 2) - 2);
  6576:   }  //popwz()
  6577:   public static int popls () throws M68kException {
  6578:     return rls ((r[15] += 4) - 4);
  6579:   }  //popls()
  6580: 
  6581:   public static int pcbs () throws M68kException {
  6582:     return rbs ((pc += 2) - 1);  //ワードの下位側
  6583:   }  //pcbs()
  6584:   public static int pcbz () throws M68kException {
  6585:     return rbz ((pc += 2) - 1);  //ワードの下位側
  6586:   }  //pcbz()
  6587:   public static int pcws () throws M68kException {
  6588:     return rwse ((pc += 2) - 2);
  6589:   }  //pcws()
  6590:   public static int pcwz () throws M68kException {
  6591:     return rwze ((pc += 2) - 2);
  6592:   }  //pcwz()
  6593:   public static int pcls () throws M68kException {
  6594:     return rlse ((pc += 4) - 4);
  6595:   }  //pcls()
  6596: 
  6597:   public static void ccr_tst (int z) {  //Xは変化しない。VとCはクリア
  6598:     ccr = z >> 28 & CCR_N | (z == 0 ? ccr & CCR_X | CCR_Z : ccr & CCR_X);  //ccr_tst
  6599:   }  //ccr_tst(int)
  6600:   public static void ccr_btst (int z) {  //Z以外は変化しない
  6601:     ccr = (ccr & (CCR_X | CCR_N | CCR_V | CCR_C) | (z == 0 ? CCR_Z : 0));
  6602:   }  //ccr_btst(int)
  6603:   public static void ccr_clr () {  //Xは変化しない。Zはセット。NとVとCはクリア
  6604:     ccr = ccr & CCR_X | CCR_Z;  //ccr_clr
  6605:   }  //ccr_clr(int)
  6606: 
  6607:   //                  x-y V                                  x-y C
  6608:   //  x  y|  0   1   2   3  -4  -3  -2  -1   x  y|  0   1   2   3   4   5   6   7
  6609:   //  ----+--------------------------------  ----+--------------------------------
  6610:   //    0 |  0  -1  -2  -3   4*  3   2   1     0 |  0  -1* -2* -3* -4* -5* -6* -7*
  6611:   //    1 |  1   0  -1  -2   5*  4*  3   2     1 |  1   0  -1* -2* -3* -4* -5* -6*
  6612:   //    2 |  2   1   0  -1   6*  5*  4*  3     2 |  2   1   0  -1* -2* -3* -4* -5*
  6613:   //    3 |  3   2   1   0   7*  6*  5*  4*    3 |  3   2   1   0  -1* -2* -3* -4*
  6614:   //   -4 | -4  -5* -6* -7*  0  -1  -2  -3     4 |  4   3   2   1   0  -1* -2* -3*
  6615:   //   -3 | -3  -4  -5* -6*  1   0  -1  -2     5 |  5   4   3   2   1   0  -1* -2*
  6616:   //   -2 | -2  -3  -4  -5*  2   1   0  -1     6 |  6   5   4   3   2   1   0  -1*
  6617:   //   -1 | -1  -2  -3  -4   3   2   1   0     7 |  7   6   5   4   3   2   1   0
  6618:   //                 x-y-1 V                                x-y-1 C
  6619:   //  x  y|  0   1   2   3  -4  -3  -2  -1   x  y|  0   1   2   3   4   5   6   7
  6620:   //  ----+--------------------------------  ----+--------------------------------
  6621:   //    0 | -1  -2  -3  -4   3   2   1   0     0 | -1* -2* -3* -4* -5* -6* -7* -8*
  6622:   //    1 |  0  -1  -2  -3   4*  3   2   1     1 |  0  -1* -2* -3* -4* -5* -6* -7*
  6623:   //    2 |  1   0  -1  -2   5*  4*  3   2     2 |  1   0  -1* -2* -3* -4* -5* -6*
  6624:   //    3 |  2   1   0  -1   6*  5*  4*  3     3 |  2   1   0  -1* -2* -3* -4* -5*
  6625:   //   -4 | -5* -6* -7* -8* -1  -2  -3  -4     4 |  3   2   1   0  -1* -2* -3* -4*
  6626:   //   -3 | -4  -5* -6* -7*  0  -1  -2  -3     5 |  4   3   2   1   0  -1* -2* -3*
  6627:   //   -2 | -3  -4  -5* -6*  1   0  -1  -2     6 |  5   4   3   2   1   0  -1* -2*
  6628:   //   -1 | -2  -3  -4  -5*  2   1   0  -1     7 |  6   5   4   3   2   1   0  -1*
  6629:   //  x        y         z=x-y    v        c         z=x-y-1  v        c
  6630:   //  00000000 00001111  01111000 00001000 01111111  11110000 00000000 11111111
  6631:   //  00000000 00001111  00111100 00001100 00111111  01111000 00001000 01111111
  6632:   //  00000000 00001111  00011110 00001110 00011111  00111100 00001100 00111111
  6633:   //  00000000 00001111  00001111 00001111 00001111  00011110 00001110 00011111
  6634:   //  11111111 00001111  10000111 01110000 00000111  00001111 11110000 00001111
  6635:   //  11111111 00001111  11000011 00110000 00000011  10000111 01110000 00000111
  6636:   //  11111111 00001111  11100001 00010000 00000001  11000011 00110000 00000011
  6637:   //  11111111 00001111  11110000 00000000 00000000  11100001 00010000 00000001
  6638:   //  Vは右上と左下でxとzが異なる部分
  6639:   //    V = ((x ^ y) & (x ^ z)) < 0
  6640:   //  Cは右上全部および左上と右下でzがある部分
  6641:   //    C = (~x & y | ~(x ^ y) & z) < 0
  6642:   //    ~を使わずに書けるおそらく最短の等価式
  6643:   //    C = (x & (y ^ z) ^ (y | z)) < 0
  6644:   //      perl -e "for$x(0..1){for$y(0..1){for$z(0..1){print join(',',$x,$y,$z,(1^$x)&$y|(1^($x^$y))&$z,$x&($y^$z)^($y|$z)).chr(10);}}}"
  6645:   //      0,0,0,0,0
  6646:   //      0,0,1,1,1
  6647:   //      0,1,0,1,1
  6648:   //      0,1,1,1,1
  6649:   //      1,0,0,0,0
  6650:   //      1,0,1,0,0
  6651:   //      1,1,0,0,0
  6652:   //      1,1,1,1,1
  6653:   public static void ccr_sub (int x, int y, int z) {
  6654:     ccr = (z >> 28 & CCR_N | (z == 0 ? CCR_Z : 0) |
  6655:            ((x ^ y) & (x ^ z)) >>> 31 << 1 |
  6656:            (x & (y ^ z) ^ (y | z)) >> 31 & (CCR_X | CCR_C));
  6657:   }  //ccr_sub(int,int,int)
  6658:   public static void ccr_subx (int x, int y, int z) {  //Zは結果が0のとき変化しない
  6659:     ccr = (z >> 28 & CCR_N | (z == 0 ? ccr & CCR_Z : 0) |
  6660:            ((x ^ y) & (x ^ z)) >>> 31 << 1 |
  6661:            (x & (y ^ z) ^ (y | z)) >> 31 & (CCR_X | CCR_C));
  6662:   }  //ccr_subx(int,int,int)
  6663:   public static void ccr_subq (int x, int y, int z) {  //ccr_subを常にy>0としたもの。Vは負→正のとき1。Cは正→負のとき1
  6664:     ccr = (z >> 28 & CCR_N | (z == 0 ? CCR_Z : 0) |
  6665:            (x & ~z) >>> 31 << 1 |
  6666:            (~x & z) >> 31 & (CCR_X | CCR_C));
  6667:   }  //ccr_subq(int,int,int)
  6668:   public static void ccr_neg (int y, int z) {  //ccr_subを常にx==0としたもの。Vは-MAX→-MAXのみ1。Cは0→0以外1
  6669:     ccr = (z >> 28 & CCR_N | (z == 0 ? CCR_Z : 0) |
  6670:            (y & z) >>> 31 << 1 |
  6671:            (y | z) >> 31 & (CCR_X | CCR_C));
  6672:   }  //ccr_neg(int,int)
  6673:   public static void ccr_negx (int y, int z) {  //ccr_subxを常にx==0としたもの。Zは結果が0のとき変化しない
  6674:     ccr = (z >> 28 & CCR_N | (z == 0 ? ccr & CCR_Z : 0) |
  6675:            (y & z) >>> 31 << 1 |
  6676:            (y | z) >> 31 & (CCR_X | CCR_C));
  6677:   }  //ccr_negx(int,int)
  6678:   public static void ccr_cmp (int x, int y, int z) {  //Xは変化しない
  6679:     ccr = (z >> 28 & CCR_N | (z == 0 ? ccr & CCR_X | CCR_Z : ccr & CCR_X) |
  6680:            ((x ^ y) & (x ^ z)) >>> 31 << 1 |
  6681:            (x & (y ^ z) ^ (y | z)) >>> 31);
  6682:   }  //ccr_cmp(int,int,int)
  6683: 
  6684:   //                  x+y V                                  x+y C
  6685:   //  x  y|  0   1   2   3  -4  -3  -2  -1   x  y|  0   1   2   3   4   5   6   7
  6686:   //  ----+--------------------------------  ----+--------------------------------
  6687:   //    0 |  0   1   2   3  -4  -3  -2  -1     0 |  0   1   2   3   4   5   6   7
  6688:   //    1 |  1   2   3   4* -3  -2  -1   0     1 |  1   2   3   4   5   6   7   8*
  6689:   //    2 |  2   3   4*  5* -2  -1   0   1     2 |  2   3   4   5   6   7   8*  9*
  6690:   //    3 |  3   4*  5*  6* -1   0   1   2     3 |  3   4   5   6   7   8*  9* 10*
  6691:   //   -4 | -4  -3  -2  -1  -8* -7* -6* -5*    4 |  4   5   6   7   8*  9* 10* 11*
  6692:   //   -3 | -3  -2  -1   0  -7* -6* -5* -4     5 |  5   6   7   8*  9* 10* 11* 12*
  6693:   //   -2 | -2  -1   0   1  -6* -5* -4  -3     6 |  6   7   8*  9* 10* 11* 12* 13*
  6694:   //   -1 | -1   0   1   2  -5* -4  -3  -2     7 |  7   8*  9* 10* 11* 12* 13* 14*
  6695:   //                 x+y+1 V                                x+y+1 C
  6696:   //  x  y|  0   1   2   3  -4  -3  -2  -1   x  y|  0   1   2   3   4   5   6   7
  6697:   //  ----+--------------------------------  ----+--------------------------------
  6698:   //    0 |  1   2   3   4* -3  -2  -1   0     0 |  1   2   3   4   5   6   7   8*
  6699:   //    1 |  2   3   4*  5* -2  -1   0   1     1 |  2   3   4   5   6   7   8*  9*
  6700:   //    2 |  3   4*  5*  6* -1   0   1   2     2 |  3   4   5   6   7   8*  9* 10*
  6701:   //    3 |  4*  5*  6*  7*  0   1   2   3     3 |  4   5   6   7   8*  9* 10* 11*
  6702:   //   -4 | -3  -2  -1   0  -7* -6* -5* -4     4 |  5   6   7   8*  9* 10* 11* 12*
  6703:   //   -3 | -2  -1   0   1  -6* -5* -4  -3     5 |  6   7   8*  9* 10* 11* 12* 13*
  6704:   //   -2 | -1   0   1   2  -5* -4  -3  -2     6 |  7   8*  9* 10* 11* 12* 13* 14*
  6705:   //   -1 |  0   1   2   3  -4  -3  -2  -1     7 |  8*  9* 10* 11* 12* 13* 14* 15*
  6706:   //  x        y         z=x+y    v        c         z=x+y+1  v        c
  6707:   //  00000000 00001111  00001111 00000000 00000000  00011110 00010000 00000001
  6708:   //  00000000 00001111  00011110 00010000 00000001  00111100 00110000 00000011
  6709:   //  00000000 00001111  00111100 00110000 00000011  01111000 01110000 00000111
  6710:   //  00000000 00001111  01111000 01110000 00000111  11110000 11110000 00001111
  6711:   //  11111111 00001111  11110000 00001111 00001111  11100001 00001110 00011111
  6712:   //  11111111 00001111  11100001 00001110 00011111  11000011 00001100 00111111
  6713:   //  11111111 00001111  11000011 00001100 00111111  10000111 00001000 01111111
  6714:   //  11111111 00001111  10000111 00001000 01111111  00001111 00000000 11111111
  6715:   //  Vは左上と右下でxとzが異なる部分
  6716:   //    V = (~(x ^ y) & (x ^ z)) < 0
  6717:   //    ~を使わずに書けるおそらく最短の等価式
  6718:   //    V = ((x ^ z) & (y ^ z)) < 0
  6719:   //      perl -e "for$x(0..1){for$y(0..1){for$z(0..1){print join(',',$x,$y,$z,(1^($x^$y))&($x^$z),($x^$z)&($y^$z)).chr(10);}}}"
  6720:   //      0,0,0,0,0
  6721:   //      0,0,1,1,1
  6722:   //      0,1,0,0,0
  6723:   //      0,1,1,0,0
  6724:   //      1,0,0,0,0
  6725:   //      1,0,1,0,0
  6726:   //      1,1,0,1,1
  6727:   //      1,1,1,0,0
  6728:   //  Cは右下全部および右上と左下でzがない部分
  6729:   //    C = (x & y | (x ^ y) & ~z) < 0
  6730:   //    ~を使わずに書けるおそらく最短の等価式
  6731:   //    C = ((x | y) ^ (x ^ y) & z) < 0
  6732:   //      perl -e "for$x(0..1){for$y(0..1){for$z(0..1){print join(',',$x,$y,$z,$x&$y|($x^$y)&(1^$z),($x|$y)^($x^$y)&$z).chr(10);}}}"
  6733:   //      0,0,0,0,0
  6734:   //      0,0,1,0,0
  6735:   //      0,1,0,1,1
  6736:   //      0,1,1,0,0
  6737:   //      1,0,0,1,1
  6738:   //      1,0,1,0,0
  6739:   //      1,1,0,1,1
  6740:   //      1,1,1,1,1
  6741:   public static void ccr_add (int x, int y, int z) {
  6742:     ccr = (z >> 28 & CCR_N | (z == 0 ? CCR_Z : 0) |
  6743:            ((x ^ z) & (y ^ z)) >>> 31 << 1 |
  6744:            ((x | y) ^ (x ^ y) & z) >> 31 & (CCR_X | CCR_C));
  6745:   }  //ccr_add(int,int,int)
  6746:   public static void ccr_addx (int x, int y, int z) {  //Zは結果が0のとき変化しない
  6747:     ccr = (z >> 28 & CCR_N | (z == 0 ? ccr & CCR_Z : 0) |
  6748:            ((x ^ z) & (y ^ z)) >>> 31 << 1 |
  6749:            ((x | y) ^ (x ^ y) & z) >> 31 & (CCR_X | CCR_C));
  6750:   }  //ccr_addx(int,int,int)
  6751:   public static void ccr_addq (int x, int y, int z) {  //ccr_addを常にy>0としたもの。Vは正→負のとき1。Cは負→正のとき1
  6752:     ccr = (z >> 28 & CCR_N | (z == 0 ? CCR_Z : 0) |
  6753:            (~x & z) >>> 31 << 1 |
  6754:            (x & ~z) >> 31 & (CCR_X | CCR_C));
  6755:   }  //ccr_addq(int,int,int)
  6756: */
  6757: 
  6758: 
  6759: 
  6760:   //========================================================================================
  6761:   //$$EFA 実効アドレス計算
  6762:   //
  6763:   //  アドレッシングモードとサイクル数
  6764:   //    DrまたはArを指定すると不当命令になる
  6765:   //    例えばArを指定できない命令ならDrだけを特別扱いにして残りをefa~に渡せばArは自動的に不当命令になる
  6766:   //    実効アドレス計算とオペランドのアクセス1回分のサイクル数がmpuCycleCountに加算される
  6767:   //                        mmm rrr  Any Mem Mlt Cnt Clt  Byte Word Long Quad Extd  LeaPea JmpJsr
  6768:   //         -------------  --- ---  --- --- --- --- ---  ---- ---- ---- ---- ----  ------ ------
  6769:   //      M  (Ar)           010 rrr    *   *   *   *   *     4    4    8   16   24       4      8
  6770:   //      +  (Ar)+          011 rrr    *   *   *             4    4    8   16   24
  6771:   //      -  -(Ar)          100 rrr    *   *   *             6    6   10   18   26
  6772:   //      W  (d16,Ar)       101 rrr    *   *   *   *   *     8    8   12   20   28       8     10
  6773:   //      X  (d8,Ar,Rn.wl)  110 rrr    *   *   *   *   *    10   10   14   22   30      12     14
  6774:   //      Z  (xxx).W        111 000    *   *   *   *   *     8    8   12   20   28       8     10
  6775:   //      Z  (xxx).L        111 001    *   *   *   *   *    12   12   16   24   32      12     12
  6776:   //      P  (d16,PC)       111 010    *   *       *         8    8   12   20   28       8     10
  6777:   //      P  (d8,PC,Rn.wl)  111 011    *   *       *        10   10   14   22   30      12     14
  6778:   //      I  #<data>        111 100    *                     4    4    8   16   24
  6779:   //    MoveToMemByte/MoveToMemWord/MoveToMemLongはデスティネーションが-(Aq)のとき2減らす
  6780:   //    AddToRegLong/AddaLong/AndToRegLong/OrToRegLong/SubToRegLong/SubaLongはソースがDr/Ar/#<data>のとき2増やす
  6781:   //
  6782:   //  フルフォーマットの拡張ワードの処理の冗長表現
  6783:   //      t = r[ea - (0b110_000 - 8)];  //ベースレジスタ
  6784:   //      w = rwze ((pc += 2) - 2);  //pcwz。拡張ワード
  6785:   //      x = r[w >> 12];  //インデックスレジスタ
  6786:   //      if ((w & 0x0800) == 0) {  //ワードインデックス
  6787:   //        x = (short) x;
  6788:   //      }
  6789:   //      x <<= w >> 9 & 3;  //スケールファクタ。ワードインデックスのときは符号拡張してから掛ける
  6790:   //      if ((w & 0x0100) == 0) {  //短縮フォーマット
  6791:   //        t += (byte) w + x;  //8ビットディスプレースメント
  6792:   //      } else {  //フルフォーマット
  6793:   //        if ((w & 0x0080) != 0) {  //ベースサプレス
  6794:   //          t = 0;
  6795:   //        }
  6796:   //        if ((w & 0x0040) != 0) {  //インデックスサプレス
  6797:   //          x = 0;
  6798:   //        }
  6799:   //        if ((w & 0x0020) != 0) {  //ベースディスプレースメントあり
  6800:   //          if ((w & 0x0010) == 0) {  //ワードベースディスプレースメント
  6801:   //            t += rwse ((pc += 2) - 2);  //pcws
  6802:   //          } else {  //ロングベースディスプレースメント
  6803:   //            t += rlse ((pc += 4) - 4);  //pcls
  6804:   //          }
  6805:   //        }
  6806:   //        if ((w & 0x0003) == 0) {  //メモリ間接なし
  6807:   //          t += x;
  6808:   //        } else {  //メモリ間接あり
  6809:   //          if ((w & 0x0004) == 0) {  //プリインデックス
  6810:   //            t = rls (t + x);
  6811:   //          } else {  //ポストインデックス
  6812:   //            t = rls (t) + x;
  6813:   //          }
  6814:   //          if ((w & 0x0002) != 0) {  //アウタディスプレースメントあり
  6815:   //            if ((w & 0x0001) == 0) {  //ワードアウタディスプレースメント
  6816:   //              t += rwse ((pc += 2) - 2);  //pcws
  6817:   //            } else {  //ロングアウタディスプレースメント
  6818:   //              t += rlse ((pc += 4) - 4);  //pcls
  6819:   //            }
  6820:   //          }
  6821:   //        }
  6822:   //      }
  6823:   //      return t;
  6824:   //
  6825:   //  フルフォーマットの拡張ワードのサイクル数
  6826:   //    ベースディスプレースメントとメモリ間接とアウターディスプレースメントのリード回数に応じてサイクル数を加算する
  6827:   //    ベースレジスタとインデックスレジスタとスケールファクタの有無はサイクル数に影響しないものとする
  6828:   //      fedcba9876543210  bd  []  od  計
  6829:   //      .......0........               0  (d8,~)
  6830:   //      .......1..01..00               0  (~)
  6831:   //      .......1..01..01       8       8  ([~])
  6832:   //      .......1..01..10       8   4  12  ([~],od.W)
  6833:   //      .......1..01..11       8   8  16  ([~],od.L)
  6834:   //      .......1..10..00   4           4  (bd.W,~)
  6835:   //      .......1..10..01   4   8      12  ([bd.W,~])
  6836:   //      .......1..10..10   4   8   4  16  ([bd.W,~],od.W)
  6837:   //      .......1..10..11   4   8   8  20  ([bd.W,~],od.L)
  6838:   //      .......1..11..00   8           8  (bd.L,~)
  6839:   //      .......1..11..01   8   8      16  ([bd.L,~])
  6840:   //      .......1..11..10   8   8   4  20  ([bd.L,~],od.W)
  6841:   //      .......1..11..11   8   8   8  24  ([bd.L,~],od.L)
  6842:   //    1つの式で書くこともできるが冗長になるのでテーブル参照にする
  6843:   //
  6844:   //  MC68060のサイクル数
  6845:   //    ブリーフフォーマットは0、フルフォーマットのメモリ間接なしは1、フルフォーマットのメモリ間接ありは3
  6846:   //
  6847: 
  6848:   //拡張ワードのサイクル数
  6849: /*
  6850:   public static final int[] EFA_EXTENSION_CLK = {                  //fedcba9876543210
  6851:     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  //.......0........
  6852:     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  //.......0........
  6853:     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  //.......0........
  6854:     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  //.......0........
  6855:     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  //.......0........
  6856:     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  //.......0........
  6857:     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  //.......0........
  6858:     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  //.......0........
  6859:     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  //.......0........
  6860:     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  //.......0........
  6861:     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  //.......0........
  6862:     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  //.......0........
  6863:     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  //.......0........
  6864:     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  //.......0........
  6865:     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  //.......0........
  6866:     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  //.......0........
  6867:     0,  8, 12, 16,  0,  8, 12, 16,  0,  8, 12, 16,  0,  8, 12, 16,  //.......1..00....
  6868:     0,  8, 12, 16,  0,  8, 12, 16,  0,  8, 12, 16,  0,  8, 12, 16,  //.......1..01....
  6869:     4, 12, 16, 20,  4, 12, 16, 20,  4, 12, 16, 20,  4, 12, 16, 20,  //.......1..10....
  6870:     8, 16, 20, 24,  8, 16, 20, 24,  8, 16, 20, 24,  8, 16, 20, 24,  //.......1..11....
  6871:     0,  8, 12, 16,  0,  8, 12, 16,  0,  8, 12, 16,  0,  8, 12, 16,  //.......1..00....
  6872:     0,  8, 12, 16,  0,  8, 12, 16,  0,  8, 12, 16,  0,  8, 12, 16,  //.......1..01....
  6873:     4, 12, 16, 20,  4, 12, 16, 20,  4, 12, 16, 20,  4, 12, 16, 20,  //.......1..10....
  6874:     8, 16, 20, 24,  8, 16, 20, 24,  8, 16, 20, 24,  8, 16, 20, 24,  //.......1..11....
  6875:     0,  8, 12, 16,  0,  8, 12, 16,  0,  8, 12, 16,  0,  8, 12, 16,  //.......1..00....
  6876:     0,  8, 12, 16,  0,  8, 12, 16,  0,  8, 12, 16,  0,  8, 12, 16,  //.......1..01....
  6877:     4, 12, 16, 20,  4, 12, 16, 20,  4, 12, 16, 20,  4, 12, 16, 20,  //.......1..10....
  6878:     8, 16, 20, 24,  8, 16, 20, 24,  8, 16, 20, 24,  8, 16, 20, 24,  //.......1..11....
  6879:     0,  8, 12, 16,  0,  8, 12, 16,  0,  8, 12, 16,  0,  8, 12, 16,  //.......1..00....
  6880:     0,  8, 12, 16,  0,  8, 12, 16,  0,  8, 12, 16,  0,  8, 12, 16,  //.......1..01....
  6881:     4, 12, 16, 20,  4, 12, 16, 20,  4, 12, 16, 20,  4, 12, 16, 20,  //.......1..10....
  6882:     8, 16, 20, 24,  8, 16, 20, 24,  8, 16, 20, 24,  8, 16, 20, 24,  //.......1..11....
  6883:   };
  6884: */
  6885:   //  perl misc/itob.pl xeij/XEiJ.java EFA_EXTENSION_CLK
  6886:   public static final byte[] EFA_EXTENSION_CLK = "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\b\f\20\0\b\f\20\0\b\f\20\0\b\f\20\0\b\f\20\0\b\f\20\0\b\f\20\0\b\f\20\4\f\20\24\4\f\20\24\4\f\20\24\4\f\20\24\b\20\24\30\b\20\24\30\b\20\24\30\b\20\24\30\0\b\f\20\0\b\f\20\0\b\f\20\0\b\f\20\0\b\f\20\0\b\f\20\0\b\f\20\0\b\f\20\4\f\20\24\4\f\20\24\4\f\20\24\4\f\20\24\b\20\24\30\b\20\24\30\b\20\24\30\b\20\24\30\0\b\f\20\0\b\f\20\0\b\f\20\0\b\f\20\0\b\f\20\0\b\f\20\0\b\f\20\0\b\f\20\4\f\20\24\4\f\20\24\4\f\20\24\4\f\20\24\b\20\24\30\b\20\24\30\b\20\24\30\b\20\24\30\0\b\f\20\0\b\f\20\0\b\f\20\0\b\f\20\0\b\f\20\0\b\f\20\0\b\f\20\0\b\f\20\4\f\20\24\4\f\20\24\4\f\20\24\4\f\20\24\b\20\24\30\b\20\24\30\b\20\24\30\b\20\24\30".getBytes (XEiJ.ISO_8859_1);
  6887: 
  6888:   public static final boolean EFA_SEPARATE_AR = false;  //true=(Ar)を(A0)~(A7)に分ける
  6889: 
  6890: 
  6891: 
  6892:   //========================================================================================
  6893:   //$$BUS バスコントローラ
  6894: 
  6895:   public static final boolean BUS_SPLIT_UNALIGNED_LONG = false;  //true=4の倍数ではない偶数アドレスへのロングワードアクセスを常に分割する
  6896: 
  6897:   //マザーボードのアドレス空間
  6898:   public static final int BUS_MOTHER_BITS = 24;  //マザーボードのアドレス空間のビット数
  6899:   public static final int BUS_MOTHER_SIZE = BUS_MOTHER_BITS < 32 ? 1 << BUS_MOTHER_BITS : 0;  //マザーボードのアドレス空間のサイズ。1<<32は1が押し出されて0になるのではなくてシフトカウントが5bitでマスクされて1<<0=1になることに注意
  6900:   public static final int BUS_MOTHER_MASK = BUS_MOTHER_SIZE - 1;  //マザーボードのアドレスのマスク。a&BUS_MOTHER_MASK
  6901:   //ダミー4bitページ
  6902:   public static final int BUS_DUMMY_4BIT_PAGE = BUS_MOTHER_SIZE;
  6903:   public static final int BUS_DUMMY_4BIT_SIZE = 2 * 512 * 512;  //256KB
  6904:   //1024ドット256色(改造)
  6905:   public static final int BUS_MODIFIED_256_PAGE = BUS_DUMMY_4BIT_PAGE + BUS_DUMMY_4BIT_SIZE;
  6906:   public static final int BUS_MODIFIED_256_SIZE = 2 * 1024 * 1024;  //2MB。上位バイト(偶数アドレス)は0
  6907:   //1024ドット65536色(改造)
  6908:   public static final int BUS_MODIFIED_65536_PAGE = BUS_MODIFIED_256_PAGE + BUS_MODIFIED_256_SIZE;
  6909:   public static final int BUS_MODIFIED_65536_SIZE = 2 * 1024 * 1024;  //2MB
  6910:   //合計
  6911:   public static final int BUS_ARRAY_SIZE = BUS_MODIFIED_65536_PAGE + BUS_MODIFIED_65536_SIZE;
  6912: 
  6913:   //ページ
  6914:   public static final int BUS_PAGE_BITS = 12;  //ページのビット数。a>>>BUS_PAGE_BITS
  6915:   public static final int BUS_PAGE_SIZE = 1 << BUS_PAGE_BITS;  //ページのサイズ
  6916:   public static final int BUS_PAGE_COUNT = 1 << (32 - BUS_PAGE_BITS);  //ページの数
  6917: 
  6918:   //ss
  6919:   public static final int MPU_SS_BYTE = 0;
  6920:   public static final int MPU_SS_WORD = 1;
  6921:   public static final int MPU_SS_LONG = 2;
  6922: 
  6923:   //wr
  6924:   public static final int MPU_WR_WRITE = 0;
  6925:   public static final int MPU_WR_READ = 1;
  6926: 
  6927:   //us
  6928:   public static final int MPU_US_USER = 0;
  6929:   public static final int MPU_US_SUPERVISOR = 1;
  6930: 
  6931:   //メモリマップ
  6932:   public static final MemoryMappedDevice[] busUserMap = new MemoryMappedDevice[BUS_PAGE_COUNT];  //ユーザモード用のメモリマップ
  6933:   public static final MemoryMappedDevice[] busSuperMap = new MemoryMappedDevice[BUS_PAGE_COUNT];  //スーパーバイザモード用のメモリマップ
  6934:   public static MemoryMappedDevice[] busMemoryMap;  //現在のメモリマップ。srS==0?um:sm。DataBreakPoint.DBP_ON==trueのときは使わない
  6935: 
  6936:   //X68000のハイメモリ
  6937:   public static boolean busHimem68000;  //true=060turboのハイメモリはX68000でも有効
  6938: 
  6939:   //X68030/Xellent30のハイメモリ
  6940:   public static final int BUS_HIGH_MEMORY_START = 0x01000000;  //X68030/Xellent30のハイメモリの開始アドレス
  6941:   public static int busHighMemorySize;  //X68030/Xellent30のハイメモリのサイズ
  6942:   public static byte[] busHighMemoryArray;  //X68030/Xellent30のハイメモリの配列
  6943:   public static boolean busHighMemorySaveOn;  //true=X68030/Xellent30のハイメモリの内容を保存する
  6944:   public static boolean busHighMemory060turboOn;  //true=060turboのハイメモリを使う
  6945: 
  6946:   //060turboのハイメモリ
  6947:   public static final int BUS_LOCAL_MEMORY_START = 0x10000000;  //060turboのハイメモリの開始アドレス
  6948:   public static int busLocalMemorySize;  //060turboのハイメモリのサイズ
  6949:   public static byte[] busLocalMemoryArray;  //060turboのハイメモリの配列
  6950:   public static boolean busLocalMemorySaveOn;  //true=060turboのハイメモリの内容を保存する
  6951: 
  6952:   //拡張メモリ
  6953:   public static final byte[] BUS_DUMMY_MEMORY_ARRAY = new byte[0];  //X68030と060turbo以外の拡張メモリの配列
  6954:   public static int busRequestExMemoryStart;  //次回起動時の拡張メモリの開始アドレス
  6955:   public static int busRequestExMemorySize;  //次回起動時の拡張メモリの長さ
  6956:   public static byte[] busRequestExMemoryArray;  //次回起動時の拡張メモリの配列。BUS_DUMMY_MEMORY_ARRAY,busHighMemoryArray,busLocalMemoryArrayのいずれか
  6957:   public static int busExMemoryStart;  //拡張メモリの開始アドレス
  6958:   public static int busExMemorySize;  //拡張メモリの長さ
  6959:   public static byte[] busExMemoryArray;  //拡張メモリの配列。BUS_DUMMY_MEMORY_ARRAY,busHighMemoryArray,busLocalMemoryArrayのいずれか
  6960: 
  6961:   //FC2ピンをカットする
  6962:   public static boolean busRequestCutFC2Pin;
  6963:   public static boolean busCutFC2Pin;
  6964: 
  6965:   //busInit ()
  6966:   //  バスコントローラを初期化する
  6967:   public static void busInit () {
  6968:     //um = new MMD[BUS_PAGE_COUNT];
  6969:     //sm = new MMD[BUS_PAGE_COUNT];
  6970:     if (!DataBreakPoint.DBP_ON) {
  6971:       busMemoryMap = busSuperMap;
  6972:     }
  6973: 
  6974:     //X68030/Xellent30のハイメモリ
  6975:     int highMemorySizeMB = Settings.sgsGetInt ("highmemory");  //X68030/Xellent30のハイメモリのサイズ
  6976:     busHighMemorySize = highMemorySizeMB == 16 ? highMemorySizeMB << 20 : 0 << 20;
  6977:     if (busHighMemorySize == 0) {
  6978:         System.out.println (Multilingual.mlnJapanese ?
  6979:                             "X68030/Xellent30 のハイメモリはありません" :
  6980:                             "X68030/Xellent30 high memory does not exists");
  6981:     } else {
  6982:       System.out.printf (Multilingual.mlnJapanese ?
  6983:                          "X68030/Xellent30 のハイメモリのサイズは %dMB です\n" :
  6984:                          "X68030/Xellent30 high memory size is %dMB\n",
  6985:                          busHighMemorySize >> 20);
  6986:     }
  6987:     busHighMemoryArray = new byte[busHighMemorySize];
  6988: 
  6989:     busHimem68000 = Settings.sgsGetOnOff ("himem68000");
  6990: 
  6991:     busHighMemorySaveOn = Settings.sgsGetOnOff ("highmemorysave");  //X68030/Xellent30のハイメモリの内容を保存するか
  6992:     busHighMemory060turboOn = Settings.sgsGetOnOff ("highmemory060turbo");
  6993: 
  6994:     byte[] highMemoryArray = Settings.sgsGetData ("highmemorydata");  //X68030/Xellent30のハイメモリの内容(gzip+base64)
  6995:     if (busHighMemorySize != 0) {  //X68030/Xellent30のハイメモリがある
  6996:       if (highMemoryArray.length != 0) {  //復元するデータがある
  6997:         System.out.println (Multilingual.mlnJapanese ?
  6998:                             "X68030/Xellent30 のハイメモリのデータを復元します" :
  6999:                             "X68030/Xellent30 high memory data is restored");
  7000:         System.arraycopy (highMemoryArray, 0, busHighMemoryArray, 0, Math.min (highMemoryArray.length, busHighMemorySize));
  7001:       } else {
  7002:         System.out.println (Multilingual.mlnJapanese ?
  7003:                             "X68030/Xellent30 のハイメモリをゼロクリアします" :
  7004:                             "X68030/Xellent30 high memory is zero-cleared");
  7005:       }
  7006:       if (highMemoryArray.length < busHighMemorySize) {
  7007:         Arrays.fill (busHighMemoryArray, highMemoryArray.length, busHighMemorySize, (byte) 0);  //復元されなかった部分をゼロクリアする
  7008:       }
  7009:     }
  7010: 
  7011:     //060turboのハイメモリ
  7012:     int localMemorySizeMB = Settings.sgsGetInt ("localmemory");  //060turboのハイメモリのサイズ
  7013:     busLocalMemorySize = (localMemorySizeMB == 16 ||
  7014:                           localMemorySizeMB == 32 ||
  7015:                           localMemorySizeMB == 64 ||
  7016:                           localMemorySizeMB == 128 ||
  7017:                           localMemorySizeMB == 256 ||
  7018:                           localMemorySizeMB == 384 ||
  7019:                           localMemorySizeMB == 512 ||
  7020:                           localMemorySizeMB == 768 ?
  7021:                           localMemorySizeMB << 20 :
  7022:                           128 << 20);
  7023:     if (busLocalMemorySize == 0) {
  7024:         System.out.println (Multilingual.mlnJapanese ?
  7025:                             "060turbo のハイメモリはありません" :
  7026:                             "060turbo high memory does not exists");
  7027:     } else {
  7028:       System.out.printf (Multilingual.mlnJapanese ?
  7029:                          "060turbo のハイメモリのサイズは %dMB です\n" :
  7030:                          "060turbo high memory size is %dMB\n",
  7031:                          busLocalMemorySize >> 20);
  7032:     }
  7033:     busLocalMemoryArray = new byte[busLocalMemorySize];
  7034: 
  7035:     busLocalMemorySaveOn = Settings.sgsGetOnOff ("localmemorysave");  //060turboのハイメモリの内容を保存するか
  7036: 
  7037:     byte[] localMemoryArray = Settings.sgsGetData ("localmemorydata");  //060turboのハイメモリの内容(gzip+base64)
  7038:     if (busLocalMemorySize != 0) {  //060turboのハイメモリがある
  7039:       if (localMemoryArray.length != 0) {  //復元するデータがある
  7040:         System.out.println (Multilingual.mlnJapanese ?
  7041:                             "060turbo のハイメモリのデータを復元します" :
  7042:                             "060turbo high memory data is restored");
  7043:         System.arraycopy (localMemoryArray, 0, busLocalMemoryArray, 0, Math.min (localMemoryArray.length, busLocalMemorySize));
  7044:       } else {
  7045:         System.out.println (Multilingual.mlnJapanese ?
  7046:                             "060turbo のハイメモリをゼロクリアします" :
  7047:                             "060turbo high memory is zero-cleared");
  7048:       }
  7049:       if (localMemoryArray.length < busLocalMemorySize) {
  7050:         Arrays.fill (busLocalMemoryArray, localMemoryArray.length, busLocalMemorySize, (byte) 0);  //復元されなかった部分をゼロクリアする
  7051:       }
  7052:     }
  7053: 
  7054:     //現在の拡張メモリ
  7055:     busExMemoryStart = busRequestExMemoryStart = 0x10000000;
  7056:     busExMemorySize = busRequestExMemorySize = 0 << 20;
  7057:     busExMemoryArray = busRequestExMemoryArray = BUS_DUMMY_MEMORY_ARRAY;
  7058: 
  7059:     //FC2ピンをカットする
  7060:     busRequestCutFC2Pin = Settings.sgsGetOnOff ("cutfc2pin");  //FC2ピンをカットする(on/off)
  7061:     busCutFC2Pin = !busRequestCutFC2Pin;
  7062: 
  7063:     busUpdateMemoryMap ();
  7064: 
  7065:   }  //busInit()
  7066: 
  7067:   //busTini ()
  7068:   //  後始末
  7069:   public static void busTini () {
  7070:     Settings.sgsPutOnOff ("himem68000", busHimem68000);
  7071:     Settings.sgsPutInt ("highmemory", busHighMemorySize >>> 20);
  7072:     Settings.sgsPutOnOff ("highmemorysave", busHighMemorySaveOn);
  7073:     Settings.sgsPutOnOff ("highmemory060turbo", busHighMemory060turboOn);
  7074:     Settings.sgsPutData ("highmemorydata", busHighMemorySaveOn ? busHighMemoryArray : new byte[0]);
  7075:     Settings.sgsPutInt ("localmemory", busLocalMemorySize >>> 20);
  7076:     Settings.sgsPutOnOff ("localmemorysave", busLocalMemorySaveOn);
  7077:     Settings.sgsPutData ("localmemorydata", busLocalMemorySaveOn ? busLocalMemoryArray : new byte[0]);
  7078:     Settings.sgsPutOnOff ("cutfc2pin", busRequestCutFC2Pin);
  7079:   }  //busTini
  7080: 
  7081:   public static void busUpdateMemoryMap () {
  7082:     if (busExMemoryStart == busRequestExMemoryStart &&
  7083:         busExMemorySize == busRequestExMemorySize &&
  7084:         busExMemoryArray == busRequestExMemoryArray &&
  7085:         busExMemoryArray.length == busExMemorySize &&
  7086:         busCutFC2Pin == busRequestCutFC2Pin) {
  7087:       return;
  7088:     }
  7089:     //拡張メモリ
  7090:     busExMemoryStart = busRequestExMemoryStart;
  7091:     busExMemorySize = busRequestExMemorySize;
  7092:     busExMemoryArray = busRequestExMemoryArray;
  7093:     if (busExMemoryArray.length != busExMemorySize) {
  7094:       byte[] newArray = new byte[busExMemorySize];
  7095:       int copySize = Math.min (busExMemoryArray.length, busExMemorySize);
  7096:       if (copySize > 0) {
  7097:         System.arraycopy (busExMemoryArray, 0, newArray, 0, copySize);
  7098:       }
  7099:       if (busExMemoryArray == busHighMemoryArray) {
  7100:         busHighMemoryArray = newArray;
  7101:       } else if (busExMemoryArray == busLocalMemoryArray) {
  7102:         busLocalMemoryArray = newArray;
  7103:       }
  7104:       busExMemoryArray = newArray;
  7105:     }
  7106:     //FC2ピンをカットする
  7107:     busCutFC2Pin = busRequestCutFC2Pin;
  7108:     //メモリマップを作る
  7109:     //  すべてのページにデバイスを割り当てること
  7110: 
  7111:     //  MMR  メインメモリ
  7112:     //  $00000000~$000FFFFF  1MB
  7113:     //  $00000000~$001FFFFF  2MB
  7114:     //  $00000000~$003FFFFF  4MB
  7115:     //  $00000000~$005FFFFF  6MB
  7116:     //  $00000000~$007FFFFF  8MB
  7117:     //  $00000000~$009FFFFF  10MB
  7118:     //  $00000000~$00BFFFFF  12MB
  7119:     //  $00000000  メインメモリ
  7120:     busSuper (MemoryMappedDevice.MMD_MMR, 0x00000000, 0x00002000);  //MMR メインメモリ
  7121:     busUser ( MemoryMappedDevice.MMD_MMR, 0x00002000, 0x00c00000);  //MMR メインメモリ
  7122: 
  7123:     //  GE0  グラフィック画面(512ドット16色ページ0)
  7124:     //  $00C00000~$00C7FFFF  512KB
  7125:     //  GE1  グラフィック画面(512ドット16色ページ1)
  7126:     //  $00C80000~$00CFFFFF  512KB
  7127:     //  GE2  グラフィック画面(512ドット16色ページ2)
  7128:     //  $00D00000~$00D7FFFF  512KB
  7129:     //  GE3  グラフィック画面(512ドット16色ページ3)
  7130:     //  $00D80000~$00DFFFFF  512KB
  7131:     //  GF0  グラフィック画面(512ドット256色ページ0)
  7132:     //  $00C00000~$00C7FFFF  512KB
  7133:     //  GF1  グラフィック画面(512ドット256色ページ1)
  7134:     //  $00C80000~$00CFFFFF  512KB
  7135:     //  GM2  グラフィック画面(メモリモード2)
  7136:     //  $00C00000~$00DFFFFF  2MB
  7137:     //  GG0  グラフィック画面(512ドット65536色)
  7138:     //  $00C00000~$00C7FFFF  512KB
  7139:     //  GH0  グラフィック画面(1024ドット16色)
  7140:     //  $00C00000~$00DFFFFF  2MB
  7141:     //  GI0  グラフィック画面(1024ドット256色)
  7142:     //  $00C00000~$00DFFFFF  2MB
  7143:     //  GJ0  グラフィック画面(1024ドット65536色)
  7144:     //  $00C00000~$00DFFFFF  2MB
  7145:     //  $00C00000  グラフィックVRAM
  7146:     busSuper (MemoryMappedDevice.MMD_GE0, 0x00c00000, 0x00c80000);  //GE0 グラフィック画面(512ドット16色ページ0)
  7147:     busSuper (MemoryMappedDevice.MMD_GE1, 0x00c80000, 0x00d00000);  //GE1 グラフィック画面(512ドット16色ページ1)
  7148:     busSuper (MemoryMappedDevice.MMD_GE2, 0x00d00000, 0x00d80000);  //GE2 グラフィック画面(512ドット16色ページ2)
  7149:     busSuper (MemoryMappedDevice.MMD_GE3, 0x00d80000, 0x00e00000);  //GE3 グラフィック画面(512ドット16色ページ3)
  7150: 
  7151:     //  TXT  テキスト画面
  7152:     //  $00E00000~$00E7FFFF  512KB
  7153:     //  $00E00000  テキストVRAM
  7154:     busSuper (MemoryMappedDevice.MMD_TXT, 0x00e00000, 0x00e80000);  //TXT テキスト画面
  7155: 
  7156:     //  CRT  CRTコントローラ
  7157:     //  $00E80000~$00E81FFF  8KB
  7158:     //  $00E80000  CRTコントローラ
  7159:     busSuper (MemoryMappedDevice.MMD_CRT, 0x00e80000, 0x00e82000);  //CRT CRTコントローラ
  7160: 
  7161:     //  VCN  ビデオコントローラ
  7162:     //  $00E82000~$00E83FFF  8KB
  7163:     //  $00E82000  パレットレジスタ
  7164:     //  $00E82400  ビデオコントローラ
  7165:     busSuper (MemoryMappedDevice.MMD_VCN, 0x00e82000, 0x00e84000);  //VCN ビデオコントローラ
  7166: 
  7167:     //  DMA  DMAコントローラ
  7168:     //  $00E84000~$00E85FFF  8KB
  7169:     //  $00E84000  DMAコントローラ
  7170:     busSuper (MemoryMappedDevice.MMD_DMA, 0x00e84000, 0x00e86000);  //DMA DMAコントローラ
  7171: 
  7172:     //  SVS  スーパーバイザ領域設定
  7173:     //  $00E86000~$00E87FFF  8KB
  7174:     //  $00E86000  スーパーバイザ領域設定
  7175:     busSuper (MemoryMappedDevice.MMD_SVS, 0x00e86000, 0x00e88000);  //SVS スーパーバイザ領域設定
  7176: 
  7177:     //  MFP  マルチファンクションペリフェラル
  7178:     //  $00E88000~$00E89FFF  8KB
  7179:     //  $00E88000  MFP
  7180:     busSuper (MemoryMappedDevice.MMD_MFP, 0x00e88000, 0x00e8a000);  //MFP MFP
  7181: 
  7182:     //  RTC  リアルタイムクロック
  7183:     //  $00E8A000~$00E8BFFF  8KB
  7184:     //  $00E8A000  RTC
  7185:     busSuper (MemoryMappedDevice.MMD_RTC_FIRST, 0x00e8a000, 0x00e8c000);  //RTC RTC
  7186: 
  7187:     //  PRT  プリンタポート
  7188:     //  $00E8C000~$00E8DFFF  8KB
  7189:     //  $00E8C000  プリンタポート
  7190:     busSuper (MemoryMappedDevice.MMD_PRN, 0x00e8c000, 0x00e8e000);  //PRN プリンタポート
  7191: 
  7192:     //  SYP  システムポート
  7193:     //  $00E8E000~$00E8FFFF  8KB
  7194:     //  $00E8E000  システムポート
  7195:     busSuper (MemoryMappedDevice.MMD_SYS, 0x00e8e000, 0x00e90000);  //SYS システムポート
  7196: 
  7197:     //  OPM  FM音源
  7198:     //  $00E90000~$00E91FFF  8KB
  7199:     //  $00E90000  FM音源
  7200:     busSuper (MemoryMappedDevice.MMD_OPM, 0x00e90000, 0x00e92000);  //OPM FM音源
  7201: 
  7202:     //  PCM  ADPCM音源
  7203:     //  $00E92000~$00E93FFF  8KB
  7204:     //  $00E92000  ADPCM音源
  7205:     busSuper (MemoryMappedDevice.MMD_PCM, 0x00e92000, 0x00e94000);  //PCM ADPCM音源
  7206: 
  7207:     //  FDC  FDコントローラ
  7208:     //  $00E94000~$00E95FFF  8KB
  7209:     //  $00E94000  FDC
  7210:     busSuper (MemoryMappedDevice.MMD_FDC, 0x00e94000, 0x00e96000);  //FDC FDコントローラ
  7211: 
  7212:     //  HDC  SASI HDコントローラ
  7213:     //  $00E96000~$00E97FFF  8KB
  7214:     //  $00E96000  HDC SASI HDコントローラ
  7215:     //  $00E96020  SPC 内蔵SCSIプロトコルコントローラ
  7216:     busSuper (MemoryMappedDevice.MMD_HDC, 0x00e96000, 0x00e98000);  //HDC SASI HDコントローラ
  7217: 
  7218:     //  SCC  シリアルコミュニケーションコントローラ
  7219:     //  $00E98000~$00E99FFF  8KB
  7220:     //  $00E98000  SCC
  7221:     busSuper (MemoryMappedDevice.MMD_SCC, 0x00e98000, 0x00e9a000);  //SCC SCC
  7222: 
  7223:     //  PPI  プログラマブルペリフェラルインタフェイス
  7224:     //  $00E9A000~$00E9BFFF  8KB
  7225:     //  $00E9A000  PPI
  7226:     busSuper (MemoryMappedDevice.MMD_PPI, 0x00e9a000, 0x00e9c000);  //PPI PPI
  7227: 
  7228:     //  IOI  I/O割り込み
  7229:     //  $00E9C000~$00E9DFFF  8KB
  7230:     //  $00E9C000  I/O割り込み
  7231:     busSuper (MemoryMappedDevice.MMD_IOI, 0x00e9c000, 0x00e9e000);  //IOI I/O割り込み
  7232: 
  7233:     //  XB1  拡張ボード領域1
  7234:     //  $00E9E000~$00E9FFFF  8KB
  7235:     //  $00E9E000  数値演算プロセッサボード(CZ-6BP1/CZ-6BP1A)
  7236:     //  $00E9E200  ツクモグラフィックアクセラレータPCMボード(TS-6BGA)
  7237:     //  $00E9F000  WINDRV
  7238:     //  $00E9F000  040Excel
  7239:     //  $00E9F020  HFS ホストファイルシステムインタフェイス
  7240:     //  $00E9F040~$00E9F047  Zキーボード
  7241:     busSuper (MemoryMappedDevice.MMD_XB1, 0x00e9e000, 0x00ea0000);  //XB1 拡張ボード領域1
  7242: 
  7243:     //  XSC  拡張SCSI
  7244:     //  $00EA0000~$00EA1FFF  8KB
  7245:     //  $00EA0000  拡張SCSI(SCSIボードCZ-6BS1/Mach-2)
  7246:     //  $00EA1FF0  TS-6BS1
  7247:     busSuper (MemoryMappedDevice.MMD_NUL, 0x00ea0000, 0x00eae000);  //MemoryMappedDevice.MMD_EXSはSPC.spcReset()で必要なときだけ接続する
  7248: 
  7249:     //  XB2  拡張ボード領域2
  7250:     //  $00EA2000~$00EAFFFF  56KB
  7251:     //  $00EA8000~$00EA9FFF  PhantomX
  7252:     //  $00EAF900  FAXボード(CZ-6BC1)
  7253:     //  $00EAFA00  MIDIボード(CZ-6BM1)
  7254:     //  $00EAFB00  パラレルボード(CZ-6BN1)
  7255:     //  $00EAFC00  RS-232Cボード(CZ-6BF1)
  7256:     //  $00EAFD00  ユニバーサルI/Oボード(CZ-6BU1)
  7257:     //  $00EAFE00  GP-IBボード(CZ-6BG1)
  7258:     //  $00EAFF00  スーパーバイザエリア設定
  7259:     //  拡張
  7260:     //  $00EAFF7F  バンクメモリのページ番号
  7261:     busSuper (MemoryMappedDevice.MMD_XB2, 0x00eae000, 0x00eb0000);  //拡張ボード領域2
  7262: 
  7263:     //  SPR  スプライト画面
  7264:     //  $00EB0000~$00EBFFFF  64KB
  7265:     //  $00EB0000  スプライトレジスタ
  7266:     //  $00EB0800  スプライトコントローラ
  7267:     //  $00EB8000  スプライトPCGエリア
  7268:     //  $00EBC000  スプライトテキストエリア0
  7269:     //  $00EBE000  スプライトテキストエリア1
  7270:     busSuper (MemoryMappedDevice.MMD_SPR, 0x00eb0000, 0x00ec0000);  //SPR スプライト画面
  7271: 
  7272:     //  XB3  拡張ボード領域3
  7273:     //  $00EC0000~$00ECFFFF  64KB
  7274:     //  $00EC0000  ユーザI/Oエリア
  7275:     //  $00EC0000  Awesome
  7276:     //  $00EC0000  Xellent30
  7277:     //  $00ECC000  Mercury
  7278:     //  $00ECE000  Neptune
  7279:     //  $00ECF000  Venus-X/030
  7280:     busSuper (MemoryMappedDevice.MMD_XB3, 0x00ec0000, 0x00ed0000);  //拡張ボード領域3
  7281: 
  7282:     //  SMR  SRAM
  7283:     //  $00ED0000~$00ED3FFF  16KB
  7284:     //  $00ED0000~$00ED7FFF  32KB。改造したとき
  7285:     //  $00ED0000~$00EDFFFF  64KB。改造したとき
  7286:     //  $00ED0000  SRAM
  7287:     busSuper (MemoryMappedDevice.MMD_SMR, 0x00ed0000, 0x00ed0000 + 16384);  //SMR SRAM
  7288:     busSuper (MemoryMappedDevice.MMD_NUL, 0x00ed0000 + 16384, 0x00ed0000 + 65536);  //空き
  7289: 
  7290:     //  XB4  拡張ボード領域4
  7291:     //  $00EE0000~$00EFFFFF  128KB
  7292:     //  $00EE0000  GAフレームバッファウインドウ(サブ)
  7293:     //  $00EF0000  GAフレームバッファウインドウ(メイン)
  7294:     //  $00EFFF00  PSX16550
  7295:     //  拡張
  7296:     //  $00EE0000~$00EFFFFF  バンクメモリ
  7297:     busSuper (MemoryMappedDevice.MMD_XB4, 0x00ee0000, 0x00f00000);  //拡張ボード領域4
  7298: 
  7299:     //  CG1  CGROM1
  7300:     //  $00F00000~$00F3FFFF  256KB。CGROM作成前
  7301:     //  $00F00000  KNJ16x16フォント(1~8区,非漢字752文字)
  7302:     //  $00F05E00  KNJ16x16フォント(16~47区,第1水準漢字3008文字)
  7303:     //  $00F1D600  KNJ16x16フォント(48~84区,第2水準漢字3478文字)
  7304:     //  $00F3A000  ANK8x8フォント(256文字)
  7305:     //  $00F3A800  ANK8x16フォント(256文字)
  7306:     //  $00F3B800  ANK12x12フォント(256文字)
  7307:     //  $00F3D000  ANK12x24フォント(256文字)
  7308:     busSuper (MemoryMappedDevice.MMD_CG1, 0x00f00000, 0x00f40000);  //CG1 CGROM1
  7309: 
  7310:     //  CG2  CGROM2
  7311:     //  $00F40000~$00FBFFFF  512KB。CGROM作成前
  7312:     //  $00F40000  KNJ24x24フォント(1~8区,非漢字752文字)
  7313:     //  $00F4D380  KNJ24x24フォント(16~47区,第1水準漢字3008文字)
  7314:     //  $00F82180  KNJ24x24フォント(48~84区,第2水準漢字3478文字)
  7315:     //  $00FBF400  [13]ANK6x12フォント(256文字)
  7316:     busSuper (MemoryMappedDevice.MMD_CG2, 0x00f40000, 0x00fc0000);  //CG2 CGROM2
  7317: 
  7318:     //  ROM  ROM
  7319:     //  $00FC0000~$00FFFFFF  256KB
  7320:     //  $00FC0000  [11,12]内蔵SCSI BIOS,[13]内蔵SCSIハンドル
  7321:     //  $00FC0200  [13]ROM Human
  7322:     //  $00FCE000  [13]ROM Float
  7323:     //  $00FD3800  [13]ROMデバッガ
  7324:     //  $00FE0000  [10,11,12]ROMデバッガ
  7325:     //  $00FE5000  [10,11,12]ROM Human
  7326:     //  $00FF0000  IPLROM
  7327:     //  $00FFD018  [10]ANK6x12フォント(254文字)
  7328:     //  $00FFD344  [11]ANK6x12フォント(254文字)
  7329:     //  $00FFD45E  [12]ANK6x12フォント(254文字)
  7330:     //  $00FFDC00  [10]ROMディスク
  7331:     busSuper (MemoryMappedDevice.MMD_ROM, 0x00fc0000, 0x01000000);  //ROM ROM
  7332: 
  7333:   }  //busUpdateMemoryMap()
  7334: 
  7335:   public static void busReset () {
  7336:     if (regSRS != 0) {  //スーパーバイザモード
  7337:       if (DataBreakPoint.DBP_ON) {
  7338:         DataBreakPoint.dbpMemoryMap = DataBreakPoint.dbpSuperMap;
  7339:       } else {
  7340:         busMemoryMap = busSuperMap;
  7341:       }
  7342:     } else {  //ユーザモード
  7343:       if (DataBreakPoint.DBP_ON) {
  7344:         DataBreakPoint.dbpMemoryMap = DataBreakPoint.dbpUserMap;
  7345:       } else {
  7346:         busMemoryMap = busUserMap;
  7347:       }
  7348:     }
  7349:   }  //busReset()
  7350: 
  7351:   //busUser (mmd, motherStartAddress, motherEndAddress)
  7352:   //  ユーザ領域にデバイスを割り当てる
  7353:   //  motherStartAddress  マザーボード開始アドレス。BUS_PAGE_SIZEで割り切れること
  7354:   //  motherEndAddress    マザーボード終了アドレス。BUS_PAGE_SIZEで割り切れること
  7355:   public static void busUser (MemoryMappedDevice mmd, int motherStartAddress, int motherEndAddress) {
  7356:     int motherStartPage = motherStartAddress >>> BUS_PAGE_BITS;  //マザーボード開始ページ
  7357:     int motherEndPage = motherEndAddress >>> BUS_PAGE_BITS;  //マザーボード終了ページ
  7358:     if (false &&
  7359:         (motherStartPage << BUS_PAGE_BITS != motherStartAddress ||
  7360:          motherEndPage << BUS_PAGE_BITS != motherEndAddress)) {  //開始アドレスまたは終了アドレスがページサイズで割り切れない
  7361:       System.out.printf ("ERROR: busUser (\"%s\", 0x%08x, 0x%08x)\n", mmd.toString (), motherStartAddress, motherEndAddress);
  7362:     }
  7363:     int exMemoryStartPage = busExMemoryStart >>> BUS_PAGE_BITS;  //拡張メモリ開始ページ
  7364:     int exMemoryEndPage = exMemoryStartPage + (busExMemorySize >>> BUS_PAGE_BITS);  //拡張メモリ終了ページ
  7365:     for (int block = 0; block < 1 << 32 - BUS_MOTHER_BITS; block++) {  //ブロック
  7366:       int blockStartPage = block << BUS_MOTHER_BITS - BUS_PAGE_BITS;  //ブロック開始ページ
  7367:       int startPage = blockStartPage + motherStartPage;  //デバイス開始ページ
  7368:       int endPage = blockStartPage + motherEndPage;  //デバイス終了ページ
  7369:       for (int page = startPage; page < endPage; page++) {  //デバイスページ
  7370:         MemoryMappedDevice superMmd = exMemoryStartPage <= page && page < exMemoryEndPage ? MemoryMappedDevice.MMD_XMM : mmd;
  7371:         busUserMap[page] = busSuperMap[page] = superMmd;
  7372:         if (InstructionBreakPoint.IBP_ON) {
  7373:           if (InstructionBreakPoint.ibpUserMap[page] != MemoryMappedDevice.MMD_IBP) {  //命令ブレークポイントがない
  7374:             InstructionBreakPoint.ibpUserMap[page] = superMmd;
  7375:           }
  7376:           if (InstructionBreakPoint.ibpSuperMap[page] != MemoryMappedDevice.MMD_IBP) {  //命令ブレークポイントがない
  7377:             InstructionBreakPoint.ibpSuperMap[page] = superMmd;
  7378:           }
  7379:         }
  7380:         if (DataBreakPoint.DBP_ON) {
  7381:           if (DataBreakPoint.dbpUserMap[page] != MemoryMappedDevice.MMD_DBP) {  //データブレークポイントがない
  7382:             DataBreakPoint.dbpUserMap[page] = superMmd;
  7383:           }
  7384:           if (DataBreakPoint.dbpSuperMap[page] != MemoryMappedDevice.MMD_DBP) {  //データブレークポイントがない
  7385:             DataBreakPoint.dbpSuperMap[page] = superMmd;
  7386:           }
  7387:         }
  7388:       }
  7389:     }
  7390:   }  //busUser(MMD,int,int)
  7391: 
  7392:   //busSuper (mmd, motherStartAddress, motherEndAddress)
  7393:   //  スーパーバイザ領域にデバイスを割り当てる
  7394:   //  motherStartAddress  マザーボード開始アドレス。BUS_PAGE_SIZEで割り切れること
  7395:   //  motherEndAddress    マザーボード終了アドレス。BUS_PAGE_SIZEで割り切れること
  7396:   public static void busSuper (MemoryMappedDevice mmd, int motherStartAddress, int motherEndAddress) {
  7397:     int motherStartPage = motherStartAddress >>> BUS_PAGE_BITS;  //マザーボード開始ページ
  7398:     int motherEndPage = motherEndAddress >>> BUS_PAGE_BITS;  //マザーボード終了ページ
  7399:     if (false &&
  7400:         (motherStartPage << BUS_PAGE_BITS != motherStartAddress ||
  7401:          motherEndPage << BUS_PAGE_BITS != motherEndAddress)) {  //開始アドレスまたは終了アドレスがページサイズで割り切れない
  7402:       System.out.printf ("ERROR: busSuper (\"%s\", 0x%08x, 0x%08x)\n", mmd.toString (), motherStartAddress, motherEndAddress);
  7403:     }
  7404:     int exMemoryStartPage = busExMemoryStart >>> BUS_PAGE_BITS;  //拡張メモリ開始ページ
  7405:     int exMemoryEndPage = exMemoryStartPage + (busExMemorySize >>> BUS_PAGE_BITS);  //拡張メモリ終了ページ
  7406:     for (int block = 0; block < 1 << 32 - BUS_MOTHER_BITS; block++) {  //ブロック
  7407:       int blockStartPage = block << BUS_MOTHER_BITS - BUS_PAGE_BITS;  //ブロック開始ページ
  7408:       int startPage = blockStartPage + motherStartPage;  //デバイス開始ページ
  7409:       int endPage = blockStartPage + motherEndPage;  //デバイス終了ページ
  7410:       for (int page = startPage; page < endPage; page++) {  //デバイスページ
  7411:         boolean isExMemory = exMemoryStartPage <= page && page < exMemoryEndPage;
  7412:         MemoryMappedDevice userMmd = isExMemory ? MemoryMappedDevice.MMD_XMM : busCutFC2Pin ? mmd : MemoryMappedDevice.MMD_NUL;
  7413:         MemoryMappedDevice superMmd = isExMemory ? MemoryMappedDevice.MMD_XMM : mmd;
  7414:         busUserMap[page] = userMmd;
  7415:         busSuperMap[page] = superMmd;
  7416:         if (InstructionBreakPoint.IBP_ON) {
  7417:           if (InstructionBreakPoint.ibpUserMap[page] != MemoryMappedDevice.MMD_IBP) {  //命令ブレークポイントがない
  7418:             InstructionBreakPoint.ibpUserMap[page] = userMmd;
  7419:           }
  7420:           if (InstructionBreakPoint.ibpSuperMap[page] != MemoryMappedDevice.MMD_IBP) {  //命令ブレークポイントがない
  7421:             InstructionBreakPoint.ibpSuperMap[page] = superMmd;
  7422:           }
  7423:         }
  7424:         if (DataBreakPoint.DBP_ON) {
  7425:           if (DataBreakPoint.dbpUserMap[page] != MemoryMappedDevice.MMD_DBP) {  //データブレークポイントがない
  7426:             DataBreakPoint.dbpUserMap[page] = userMmd;
  7427:           }
  7428:           if (DataBreakPoint.dbpSuperMap[page] != MemoryMappedDevice.MMD_DBP) {  //データブレークポイントがない
  7429:             DataBreakPoint.dbpSuperMap[page] = superMmd;
  7430:           }
  7431:         }
  7432:       }
  7433:     }
  7434:   }  //busSuper(MMD,int,int)
  7435: 
  7436:   //d = busPbs (a)
  7437:   //  ピークバイト符号拡張
  7438:   public static byte busPbs (int a) {
  7439:     return busSuperMap[a >>> BUS_PAGE_BITS].mmdPbs (a);
  7440:   }  //busPbs(int)
  7441: 
  7442:   //d = busPbz (a)
  7443:   //  ピークバイトゼロ拡張
  7444:   public static int busPbz (int a) {
  7445:     return busSuperMap[a >>> BUS_PAGE_BITS].mmdPbz (a);
  7446:   }  //busPbz(int)
  7447: 
  7448:   //d = busPws (a)
  7449:   //  ピークワード符号拡張
  7450:   public static int busPws (int a) {
  7451:     if (TEST_BIT_0_SHIFT ? a << 31 - 0 >= 0 : (a & 1) == 0) {  //偶数
  7452:       return busSuperMap[a >>> BUS_PAGE_BITS].mmdPws (a);
  7453:     } else {  //奇数
  7454:       int a1 = a + 1;
  7455:       return busSuperMap[a >>> BUS_PAGE_BITS].mmdPbs (a) << 8 | busSuperMap[a1 >>> BUS_PAGE_BITS].mmdPbz (a1);
  7456:     }
  7457:   }  //busPws(int)
  7458: 
  7459:   //d = busPwse (a)
  7460:   //  ピークワード符号拡張(偶数)
  7461:   public static int busPwse (int a) {
  7462:     return busSuperMap[a >>> BUS_PAGE_BITS].mmdPws (a);
  7463:   }  //busPwse(int)
  7464: 
  7465:   //d = busPwz (a)
  7466:   //  ピークワードゼロ拡張
  7467:   public static int busPwz (int a) {
  7468:     if (TEST_BIT_0_SHIFT ? a << 31 - 0 >= 0 : (a & 1) == 0) {  //偶数
  7469:       return busSuperMap[a >>> BUS_PAGE_BITS].mmdPwz (a);
  7470:     } else {  //奇数
  7471:       int a1 = a + 1;
  7472:       return busSuperMap[a >>> BUS_PAGE_BITS].mmdPbz (a) << 8 | busSuperMap[a1 >>> BUS_PAGE_BITS].mmdPbz (a1);
  7473:     }
  7474:   }  //busPwz(int)
  7475: 
  7476:   //d = busPwze (a)
  7477:   //  ピークワードゼロ拡張(偶数)
  7478:   public static int busPwze (int a) {
  7479:     return busSuperMap[a >>> BUS_PAGE_BITS].mmdPwz (a);
  7480:   }  //busPwze(int)
  7481: 
  7482:   //d = busPls (a)
  7483:   //  ピークロング符号拡張
  7484:   public static int busPls (int a) {
  7485:     if (TEST_BIT_0_SHIFT && TEST_BIT_1_SHIFT ? a << 30 == 0 : (a & 3) == 0) {  //4の倍数
  7486:       return busSuperMap[a >>> BUS_PAGE_BITS].mmdPls (a);
  7487:     } else if (TEST_BIT_0_SHIFT ? a << 31 - 0 >= 0 : (a & 1) == 0) {  //4の倍数ではない偶数
  7488:       int a2 = a + 2;
  7489:       return busSuperMap[a >>> BUS_PAGE_BITS].mmdPws (a) << 16 | busSuperMap[a2 >>> BUS_PAGE_BITS].mmdPwz (a2);
  7490:     } else {  //奇数
  7491:       int a1 = a + 1;
  7492:       int a3 = a + 3;
  7493:       return busSuperMap[a >>> BUS_PAGE_BITS].mmdPbs (a) << 24 | busSuperMap[a1 >>> BUS_PAGE_BITS].mmdPwz (a1) << 8 | busSuperMap[a3 >>> BUS_PAGE_BITS].mmdPbz (a3);
  7494:     }
  7495:   }  //busPls(int)
  7496: 
  7497:   //d = busPlsf (a)
  7498:   //  ピークロング符号拡張(4の倍数)
  7499:   public static int busPlsf (int a) {
  7500:     return busSuperMap[a >>> BUS_PAGE_BITS].mmdPls (a);
  7501:   }  //busPlsf(int)
  7502: 
  7503:   //d = busPqs (a)
  7504:   //  ピーククワッド符号拡張
  7505:   public static long busPqs (int a) {
  7506:     return (long) busPls (a) << 32 | busPls (a + 4) & 0xffffffffL;
  7507:   }  //busPqs(int)
  7508: 
  7509: 
  7510:   //検索
  7511:   public static int busSearchByte (int start, int end, int c) {
  7512:     for (int a = start; a < end; a++) {
  7513:       if (busSuperMap[a >>> BUS_PAGE_BITS].mmdPbz (a) == c) {
  7514:         return a;
  7515:       }
  7516:     }
  7517:     return -1;
  7518:   }
  7519:   public static int busSearchWord (int start, int end, int c) {
  7520:     for (int a = start; a < end; a += 2) {
  7521:       if (busSuperMap[a >>> BUS_PAGE_BITS].mmdPwz (a) == c) {
  7522:         return a;
  7523:       }
  7524:     }
  7525:     return -1;
  7526:   }
  7527:   public static int busSearchByteArray (int start, int end, int[] array) {
  7528:     int l = array.length;
  7529:     end -= l;
  7530:     int c = array[0];
  7531:   a:
  7532:     for (int a = start; a <= end; a++) {
  7533:       if (busSuperMap[a >>> BUS_PAGE_BITS].mmdPbz (a) != c) {
  7534:         continue a;
  7535:       }
  7536:       for (int i = 1, b = a + 1; i < l; i++, b++) {
  7537:         if (busSuperMap[b >>> BUS_PAGE_BITS].mmdPbz (b) != array[i]) {
  7538:           continue a;
  7539:         }
  7540:       }
  7541:       return a;
  7542:     }
  7543:     return -1;
  7544:   }
  7545:   public static int busSearchWordArray (int start, int end, int[] array) {
  7546:     int l = array.length;
  7547:     end -= l;
  7548:     int c = array[0];
  7549:   a:
  7550:     for (int a = start; a <= end; a += 2) {
  7551:       if (busSuperMap[a >>> BUS_PAGE_BITS].mmdPwz (a) != c) {
  7552:           continue a;
  7553:       }
  7554:       for (int i = 1, b = a + 2; i < l; i++, b += 2) {
  7555:         if (busSuperMap[b >>> BUS_PAGE_BITS].mmdPwz (b) != array[i]) {
  7556:           continue a;
  7557:         }
  7558:       }
  7559:       return a;
  7560:     }
  7561:     return -1;
  7562:   }
  7563: 
  7564: 
  7565:   //d = busRbs (a)
  7566:   //  リードバイト符号拡張
  7567:   public static byte busRbs (int a) throws M68kException {
  7568:     if (DataBreakPoint.DBP_ON) {
  7569:       return DataBreakPoint.dbpMemoryMap[a >>> BUS_PAGE_BITS].mmdRbs (a);
  7570:     } else {
  7571:       return busMemoryMap[a >>> BUS_PAGE_BITS].mmdRbs (a);
  7572:     }
  7573:   }  //busRbs(int)
  7574: 
  7575:   //d = busRbz (a)
  7576:   //  リードバイトゼロ拡張
  7577:   public static int busRbz (int a) throws M68kException {
  7578:     if (DataBreakPoint.DBP_ON) {
  7579:       return DataBreakPoint.dbpMemoryMap[a >>> BUS_PAGE_BITS].mmdRbz (a);
  7580:     } else {
  7581:       return busMemoryMap[a >>> BUS_PAGE_BITS].mmdRbz (a);
  7582:     }
  7583:   }  //busRbz(int)
  7584: 
  7585:   //d = busRws (a)
  7586:   //  リードワード符号拡張
  7587:   public static int busRws (int a) throws M68kException {
  7588:     if (TEST_BIT_0_SHIFT ? a << 31 - 0 >= 0 : (a & 1) == 0) {  //偶数
  7589:       if (DataBreakPoint.DBP_ON) {
  7590:         return DataBreakPoint.dbpMemoryMap[a >>> BUS_PAGE_BITS].mmdRws (a);
  7591:       } else {
  7592:         return busMemoryMap[a >>> BUS_PAGE_BITS].mmdRws (a);
  7593:       }
  7594:     } else if (mpuIgnoreAddressError) {  //奇数でアドレスエラーを検出しない
  7595:       int a1 = a + 1;
  7596:       if (DataBreakPoint.DBP_ON) {
  7597:         return DataBreakPoint.dbpMemoryMap[a >>> BUS_PAGE_BITS].mmdRbs (a) << 8 | DataBreakPoint.dbpMemoryMap[a1 >>> BUS_PAGE_BITS].mmdRbz (a1);
  7598:       } else {
  7599:         return busMemoryMap[a >>> BUS_PAGE_BITS].mmdRbs (a) << 8 | busMemoryMap[a1 >>> BUS_PAGE_BITS].mmdRbz (a1);
  7600:       }
  7601:     } else {  //奇数でアドレスエラーを検出する
  7602:       M68kException.m6eNumber = M68kException.M6E_ADDRESS_ERROR;
  7603:       M68kException.m6eAddress = a;
  7604:       M68kException.m6eDirection = MPU_WR_READ;
  7605:       M68kException.m6eSize = MPU_SS_WORD;
  7606:       throw M68kException.m6eSignal;
  7607:     }
  7608:   }  //busRws(int)
  7609: 
  7610:   //d = busRwse (a)
  7611:   //  リードワード符号拡張(偶数限定)
  7612:   //  MOVEM命令の2ワード目以降など、アドレスが偶数であることが分かっている場合
  7613:   public static int busRwse (int a) throws M68kException {
  7614:     if (DataBreakPoint.DBP_ON) {
  7615:       return DataBreakPoint.dbpMemoryMap[a >>> BUS_PAGE_BITS].mmdRws (a);
  7616:     } else {
  7617:       return busMemoryMap[a >>> BUS_PAGE_BITS].mmdRws (a);
  7618:     }
  7619:   }  //busRwse(int)
  7620: 
  7621:   //d = busRwz (a)
  7622:   //  リードワードゼロ拡張
  7623:   public static int busRwz (int a) throws M68kException {
  7624:     if (TEST_BIT_0_SHIFT ? a << 31 - 0 >= 0 : (a & 1) == 0) {  //偶数
  7625:       if (DataBreakPoint.DBP_ON) {
  7626:         return DataBreakPoint.dbpMemoryMap[a >>> BUS_PAGE_BITS].mmdRwz (a);
  7627:       } else {
  7628:         return busMemoryMap[a >>> BUS_PAGE_BITS].mmdRwz (a);
  7629:       }
  7630:     } else if (mpuIgnoreAddressError) {  //奇数でアドレスエラーを検出しない
  7631:       int a1 = a + 1;
  7632:       if (DataBreakPoint.DBP_ON) {
  7633:         return DataBreakPoint.dbpMemoryMap[a >>> BUS_PAGE_BITS].mmdRbz (a) << 8 | DataBreakPoint.dbpMemoryMap[a1 >>> BUS_PAGE_BITS].mmdRbz (a1);
  7634:       } else {
  7635:         return busMemoryMap[a >>> BUS_PAGE_BITS].mmdRbz (a) << 8 | busMemoryMap[a1 >>> BUS_PAGE_BITS].mmdRbz (a1);
  7636:       }
  7637:     } else {  //奇数でアドレスエラーを検出する
  7638:       M68kException.m6eNumber = M68kException.M6E_ADDRESS_ERROR;
  7639:       M68kException.m6eAddress = a;
  7640:       M68kException.m6eDirection = MPU_WR_READ;
  7641:       M68kException.m6eSize = MPU_SS_WORD;
  7642:       throw M68kException.m6eSignal;
  7643:     }
  7644:   }  //busRwz(int)
  7645: 
  7646:   //d = busRwze (a)
  7647:   //  リードワードゼロ拡張(偶数限定)
  7648:   //  MOVEM命令の2ワード目以降など、アドレスが偶数であることが分かっている場合
  7649:   public static int busRwze (int a) throws M68kException {
  7650:     if (DataBreakPoint.DBP_ON) {
  7651:       return DataBreakPoint.dbpMemoryMap[a >>> BUS_PAGE_BITS].mmdRwz (a);
  7652:     } else {
  7653:       return busMemoryMap[a >>> BUS_PAGE_BITS].mmdRwz (a);
  7654:     }
  7655:   }  //busRwze(int)
  7656: 
  7657:   //d = busRls (a)
  7658:   //  リードロング符号拡張
  7659:   public static int busRls (int a) throws M68kException {
  7660:     if (TEST_BIT_0_SHIFT && TEST_BIT_1_SHIFT ? a << 30 == 0 : (a & 3) == 0) {  //4の倍数
  7661:       if (DataBreakPoint.DBP_ON) {
  7662:         return DataBreakPoint.dbpMemoryMap[a >>> BUS_PAGE_BITS].mmdRls (a);
  7663:       } else {
  7664:         return busMemoryMap[a >>> BUS_PAGE_BITS].mmdRls (a);
  7665:       }
  7666:     } else if (TEST_BIT_0_SHIFT ? a << 31 - 0 >= 0 : (a & 1) == 0) {  //4の倍数ではない偶数
  7667:       int a2 = a + 2;
  7668:       if (BUS_SPLIT_UNALIGNED_LONG) {  //常に分割する
  7669:         if (DataBreakPoint.DBP_ON) {
  7670:           return DataBreakPoint.dbpMemoryMap[a >>> BUS_PAGE_BITS].mmdRws (a) << 16 | DataBreakPoint.dbpMemoryMap[a2 >>> BUS_PAGE_BITS].mmdRwz (a2);
  7671:         } else {
  7672:           return busMemoryMap[a >>> BUS_PAGE_BITS].mmdRws (a) << 16 | busMemoryMap[a2 >>> BUS_PAGE_BITS].mmdRwz (a2);
  7673:         }
  7674:       } else {  //デバイスを跨がないとき分割しない
  7675:         MemoryMappedDevice mmd;
  7676:         MemoryMappedDevice mmd2;
  7677:         if (DataBreakPoint.DBP_ON) {
  7678:           mmd = DataBreakPoint.dbpMemoryMap[a >>> BUS_PAGE_BITS];
  7679:           mmd2 = DataBreakPoint.dbpMemoryMap[a2 >>> BUS_PAGE_BITS];
  7680:         } else {
  7681:           mmd = busMemoryMap[a >>> BUS_PAGE_BITS];
  7682:           mmd2 = busMemoryMap[a2 >>> BUS_PAGE_BITS];
  7683:         }
  7684:         return mmd == mmd2 ? mmd.mmdRls (a) : mmd.mmdRws (a) << 16 | mmd2.mmdRwz (a2);  //デバイスを跨がない/デバイスを跨ぐ
  7685:       }
  7686:     } else if (mpuIgnoreAddressError) {  //奇数でアドレスエラーを検出しない
  7687:       int a1 = a + 1;
  7688:       int a3 = a + 3;
  7689:       if (DataBreakPoint.DBP_ON) {
  7690:         return DataBreakPoint.dbpMemoryMap[a >>> BUS_PAGE_BITS].mmdRbs (a) << 24 | DataBreakPoint.dbpMemoryMap[a1 >>> BUS_PAGE_BITS].mmdRwz (a1) << 8 | DataBreakPoint.dbpMemoryMap[a3 >>> BUS_PAGE_BITS].mmdRbz (a3);
  7691:       } else {
  7692:         return busMemoryMap[a >>> BUS_PAGE_BITS].mmdRbs (a) << 24 | busMemoryMap[a1 >>> BUS_PAGE_BITS].mmdRwz (a1) << 8 | busMemoryMap[a3 >>> BUS_PAGE_BITS].mmdRbz (a3);
  7693:       }
  7694:     } else {  //奇数でアドレスエラーを検出する
  7695:       M68kException.m6eNumber = M68kException.M6E_ADDRESS_ERROR;
  7696:       M68kException.m6eAddress = a;
  7697:       M68kException.m6eDirection = MPU_WR_READ;
  7698:       M68kException.m6eSize = MPU_SS_LONG;
  7699:       throw M68kException.m6eSignal;
  7700:     }
  7701:   }  //busRls(int)
  7702: 
  7703:   //d = busRlse (a)
  7704:   //  リードロング符号拡張(偶数限定)
  7705:   //  MOVEM命令の2ワード目以降など、アドレスが偶数であることが分かっている場合
  7706:   public static int busRlse (int a) throws M68kException {
  7707:     if (TEST_BIT_0_SHIFT && TEST_BIT_1_SHIFT ? a << 30 == 0 : (a & 3) == 0) {  //4の倍数
  7708:       if (DataBreakPoint.DBP_ON) {
  7709:         return DataBreakPoint.dbpMemoryMap[a >>> BUS_PAGE_BITS].mmdRls (a);
  7710:       } else {
  7711:         return busMemoryMap[a >>> BUS_PAGE_BITS].mmdRls (a);
  7712:       }
  7713:     } else {  //4の倍数ではない偶数
  7714:       int a2 = a + 2;
  7715:       if (BUS_SPLIT_UNALIGNED_LONG) {  //常に分割する
  7716:         if (DataBreakPoint.DBP_ON) {
  7717:           return DataBreakPoint.dbpMemoryMap[a >>> BUS_PAGE_BITS].mmdRws (a) << 16 | DataBreakPoint.dbpMemoryMap[a2 >>> BUS_PAGE_BITS].mmdRwz (a2);
  7718:         } else {
  7719:           return busMemoryMap[a >>> BUS_PAGE_BITS].mmdRws (a) << 16 | busMemoryMap[a2 >>> BUS_PAGE_BITS].mmdRwz (a2);
  7720:         }
  7721:       } else {  //デバイスを跨がないとき分割しない
  7722:         MemoryMappedDevice mmd;
  7723:         MemoryMappedDevice mmd2;
  7724:         if (DataBreakPoint.DBP_ON) {
  7725:           mmd = DataBreakPoint.dbpMemoryMap[a >>> BUS_PAGE_BITS];
  7726:           mmd2 = DataBreakPoint.dbpMemoryMap[a2 >>> BUS_PAGE_BITS];
  7727:         } else {
  7728:           mmd = busMemoryMap[a >>> BUS_PAGE_BITS];
  7729:           mmd2 = busMemoryMap[a2 >>> BUS_PAGE_BITS];
  7730:         }
  7731:         return mmd == mmd2 ? mmd.mmdRls (a) : mmd.mmdRws (a) << 16 | mmd2.mmdRwz (a2);  //デバイスを跨がない/デバイスを跨ぐ
  7732:       }
  7733:     }
  7734:   }  //busRlse(int)
  7735: 
  7736:   //d = busRlsf (a)
  7737:   //  リードロング符号拡張(4の倍数限定)
  7738:   //  例外ベクタテーブルなど、アドレスが4の倍数であることが分かっている場合
  7739:   public static int busRlsf (int a) throws M68kException {
  7740:     if (DataBreakPoint.DBP_ON) {
  7741:       return DataBreakPoint.dbpMemoryMap[a >>> BUS_PAGE_BITS].mmdRls (a);
  7742:     } else {
  7743:       return busMemoryMap[a >>> BUS_PAGE_BITS].mmdRls (a);
  7744:     }
  7745:   }  //busRlsf(int)
  7746: 
  7747:   //d = busRqs (a)
  7748:   //  リードクワッド符号拡張
  7749:   public static long busRqs (int a) throws M68kException {
  7750:     return (long) busRls (a) << 32 | busRls (a + 4) & 0xffffffffL;
  7751:   }  //busRqs(int)
  7752: 
  7753:   //busWb (a, d)
  7754:   //  ライトバイト
  7755:   public static void busWb (int a, int d) throws M68kException {
  7756:     if (DataBreakPoint.DBP_ON) {
  7757:       DataBreakPoint.dbpMemoryMap[a >>> BUS_PAGE_BITS].mmdWb (a, d);
  7758:     } else {
  7759:       busMemoryMap[a >>> BUS_PAGE_BITS].mmdWb (a, d);
  7760:     }
  7761:   }  //busWb(int,int)
  7762: 
  7763:   //busWw (a, d)
  7764:   //  ライトワード
  7765:   public static void busWw (int a, int d) throws M68kException {
  7766:     if (TEST_BIT_0_SHIFT ? a << 31 - 0 >= 0 : (a & 1) == 0) {  //偶数
  7767:       if (DataBreakPoint.DBP_ON) {
  7768:         DataBreakPoint.dbpMemoryMap[a >>> BUS_PAGE_BITS].mmdWw (a, d);
  7769:       } else {
  7770:         busMemoryMap[a >>> BUS_PAGE_BITS].mmdWw (a, d);
  7771:       }
  7772:     } else if (mpuIgnoreAddressError) {  //奇数でアドレスエラーを検出しない
  7773:       int a1 = a + 1;
  7774:       if (DataBreakPoint.DBP_ON) {
  7775:         DataBreakPoint.dbpMemoryMap[a >>> BUS_PAGE_BITS].mmdWb (a, d >> 8);
  7776:         DataBreakPoint.dbpMemoryMap[a1 >>> BUS_PAGE_BITS].mmdWb (a1, d);
  7777:       } else {
  7778:         busMemoryMap[a >>> BUS_PAGE_BITS].mmdWb (a, d >> 8);
  7779:         busMemoryMap[a1 >>> BUS_PAGE_BITS].mmdWb (a1, d);
  7780:       }
  7781:     } else {  //奇数でアドレスエラーを検出する
  7782:       M68kException.m6eNumber = M68kException.M6E_ADDRESS_ERROR;
  7783:       M68kException.m6eAddress = a;
  7784:       M68kException.m6eDirection = MPU_WR_WRITE;
  7785:       M68kException.m6eSize = MPU_SS_WORD;
  7786:       throw M68kException.m6eSignal;
  7787:     }
  7788:   }  //busWw(int,int)
  7789: 
  7790:   //busWwe (a, d)
  7791:   //  ライトワード(偶数限定)
  7792:   //  MOVEM命令の2ワード目以降など、アドレスが偶数であることが分かっている場合
  7793:   public static void busWwe (int a, int d) throws M68kException {
  7794:     if (DataBreakPoint.DBP_ON) {
  7795:       DataBreakPoint.dbpMemoryMap[a >>> BUS_PAGE_BITS].mmdWw (a, d);
  7796:     } else {
  7797:       busMemoryMap[a >>> BUS_PAGE_BITS].mmdWw (a, d);
  7798:     }
  7799:   }  //busWwe(int,int)
  7800: 
  7801:   //busWl (a, d)
  7802:   //  ライトロング
  7803:   public static void busWl (int a, int d) throws M68kException {
  7804:     if (TEST_BIT_0_SHIFT && TEST_BIT_1_SHIFT ? a << 30 == 0 : (a & 3) == 0) {  //4の倍数
  7805:       if (DataBreakPoint.DBP_ON) {
  7806:         DataBreakPoint.dbpMemoryMap[a >>> BUS_PAGE_BITS].mmdWl (a, d);
  7807:       } else {
  7808:         busMemoryMap[a >>> BUS_PAGE_BITS].mmdWl (a, d);
  7809:       }
  7810:     } else if (TEST_BIT_0_SHIFT ? a << 31 - 0 >= 0 : (a & 1) == 0) {  //4の倍数ではない偶数
  7811:       int a2 = a + 2;
  7812:       if (BUS_SPLIT_UNALIGNED_LONG) {  //常に分割する
  7813:         if (DataBreakPoint.DBP_ON) {
  7814:           DataBreakPoint.dbpMemoryMap[a >>> BUS_PAGE_BITS].mmdWw (a, d >> 16);
  7815:           DataBreakPoint.dbpMemoryMap[a2 >>> BUS_PAGE_BITS].mmdWw (a2, d);
  7816:         } else {
  7817:           busMemoryMap[a >>> BUS_PAGE_BITS].mmdWw (a, d >> 16);
  7818:           busMemoryMap[a2 >>> BUS_PAGE_BITS].mmdWw (a2, d);
  7819:         }
  7820:       } else {  //デバイスを跨がないとき分割しない
  7821:         MemoryMappedDevice mmd;
  7822:         MemoryMappedDevice mmd2;
  7823:         if (DataBreakPoint.DBP_ON) {
  7824:           mmd = DataBreakPoint.dbpMemoryMap[a >>> BUS_PAGE_BITS];
  7825:           mmd2 = DataBreakPoint.dbpMemoryMap[a2 >>> BUS_PAGE_BITS];
  7826:         } else {
  7827:           mmd = busMemoryMap[a >>> BUS_PAGE_BITS];
  7828:           mmd2 = busMemoryMap[a2 >>> BUS_PAGE_BITS];
  7829:         }
  7830:         if (mmd == mmd2) {  //デバイスを跨がない
  7831:           mmd.mmdWl (a, d);
  7832:         } else {  //デバイスを跨ぐ
  7833:           mmd.mmdWw (a, d >> 16);
  7834:           mmd2.mmdWw (a2, d);
  7835:         }
  7836:       }
  7837:     } else if (mpuIgnoreAddressError) {  //奇数でアドレスエラーを検出しない
  7838:       int a1 = a + 1;
  7839:       int a3 = a + 3;
  7840:       if (DataBreakPoint.DBP_ON) {
  7841:         DataBreakPoint.dbpMemoryMap[a >>> BUS_PAGE_BITS].mmdWb (a, d >> 24);
  7842:         DataBreakPoint.dbpMemoryMap[a1 >>> BUS_PAGE_BITS].mmdWw (a1, d >> 8);
  7843:         DataBreakPoint.dbpMemoryMap[a3 >>> BUS_PAGE_BITS].mmdWb (a3, d);
  7844:       } else {
  7845:         busMemoryMap[a >>> BUS_PAGE_BITS].mmdWb (a, d >> 24);
  7846:         busMemoryMap[a1 >>> BUS_PAGE_BITS].mmdWw (a1, d >> 8);
  7847:         busMemoryMap[a3 >>> BUS_PAGE_BITS].mmdWb (a3, d);
  7848:       }
  7849:     } else {  //奇数でアドレスエラーを検出する
  7850:       M68kException.m6eNumber = M68kException.M6E_ADDRESS_ERROR;
  7851:       M68kException.m6eAddress = a;
  7852:       M68kException.m6eDirection = MPU_WR_WRITE;
  7853:       M68kException.m6eSize = MPU_SS_LONG;
  7854:       throw M68kException.m6eSignal;
  7855:     }
  7856:   }  //busWl(int,int)
  7857: 
  7858:   //busWlf (a, d)
  7859:   //  ライトロング(4の倍数限定)
  7860:   //  例外ベクタテーブルなど、アドレスが4の倍数であることが分かっている場合
  7861:   public static void busWlf (int a, int d) throws M68kException {
  7862:     if (DataBreakPoint.DBP_ON) {
  7863:       DataBreakPoint.dbpMemoryMap[a >>> BUS_PAGE_BITS].mmdWl (a, d);
  7864:     } else {
  7865:       busMemoryMap[a >>> BUS_PAGE_BITS].mmdWl (a, d);
  7866:     }
  7867:   }  //busWlf(int,int)
  7868: 
  7869:   //busWle (a, d)
  7870:   //  ライトロング(偶数限定)
  7871:   //  MOVEM命令の2ワード目以降など、アドレスが偶数であることが分かっている場合
  7872:   public static void busWle (int a, int d) throws M68kException {
  7873:     if (TEST_BIT_0_SHIFT && TEST_BIT_1_SHIFT ? a << 30 == 0 : (a & 3) == 0) {  //4の倍数
  7874:       if (DataBreakPoint.DBP_ON) {
  7875:         DataBreakPoint.dbpMemoryMap[a >>> BUS_PAGE_BITS].mmdWl (a, d);
  7876:       } else {
  7877:         busMemoryMap[a >>> BUS_PAGE_BITS].mmdWl (a, d);
  7878:       }
  7879:     } else {  //4の倍数ではない偶数
  7880:       int a2 = a + 2;
  7881:       if (BUS_SPLIT_UNALIGNED_LONG) {  //常に分割する
  7882:         if (DataBreakPoint.DBP_ON) {
  7883:           DataBreakPoint.dbpMemoryMap[a >>> BUS_PAGE_BITS].mmdWw (a, d >> 16);
  7884:           DataBreakPoint.dbpMemoryMap[a2 >>> BUS_PAGE_BITS].mmdWw (a2, d);
  7885:         } else {
  7886:           busMemoryMap[a >>> BUS_PAGE_BITS].mmdWw (a, d >> 16);
  7887:           busMemoryMap[a2 >>> BUS_PAGE_BITS].mmdWw (a2, d);
  7888:         }
  7889:       } else {  //デバイスを跨がないとき分割しない
  7890:         MemoryMappedDevice mmd;
  7891:         MemoryMappedDevice mmd2;
  7892:         if (DataBreakPoint.DBP_ON) {
  7893:           mmd = DataBreakPoint.dbpMemoryMap[a >>> BUS_PAGE_BITS];
  7894:           mmd2 = DataBreakPoint.dbpMemoryMap[a2 >>> BUS_PAGE_BITS];
  7895:         } else {
  7896:           mmd = busMemoryMap[a >>> BUS_PAGE_BITS];
  7897:           mmd2 = busMemoryMap[a2 >>> BUS_PAGE_BITS];
  7898:         }
  7899:         if (mmd == mmd2) {  //デバイスを跨がない
  7900:           mmd.mmdWl (a, d);
  7901:         } else {  //デバイスを跨ぐ
  7902:           mmd.mmdWw (a, d >> 16);
  7903:           mmd2.mmdWw (a2, d);
  7904:         }
  7905:       }
  7906:     }
  7907:   }  //busWle(int,int)
  7908: 
  7909:   //busWq (a, d)
  7910:   //  ライトクワッド
  7911:   public static void busWq (int a, long d) throws M68kException {
  7912:     busWl (a, (int) (d >>> 32));
  7913:     busWl (a + 4, (int) d);
  7914:   }  //busWq(int,long)
  7915: 
  7916:   //以下は拡張
  7917: 
  7918:   //busRbb (a, bb, o, l)
  7919:   //  リードバイトバッファ
  7920:   public static void busRbb (int a, byte[] bb, int o, int l) throws M68kException {
  7921:     if (false) {
  7922:       for (int i = 0; i < l; i++) {
  7923:         int ai = a + i;
  7924:         if (DataBreakPoint.DBP_ON) {
  7925:           bb[o + i] = DataBreakPoint.dbpMemoryMap[ai >>> BUS_PAGE_BITS].mmdRbs (ai);
  7926:         } else {
  7927:           bb[o + i] = busMemoryMap[ai >>> BUS_PAGE_BITS].mmdRbs (ai);
  7928:         }
  7929:       }
  7930:     } else {
  7931:       int r = (~a & BUS_PAGE_SIZE - 1) + 1;  //最初のページの残りの長さ。1~BUS_PAGE_SIZE
  7932:       while (l > 0) {
  7933:         MemoryMappedDevice mmd;
  7934:         if (DataBreakPoint.DBP_ON) {
  7935:           mmd = DataBreakPoint.dbpMemoryMap[a >>> BUS_PAGE_BITS];  //ページのデバイス
  7936:         } else {
  7937:           mmd = busMemoryMap[a >>> BUS_PAGE_BITS];  //ページのデバイス
  7938:         }
  7939:         int s = l <= r ? l : r;  //このページで転送する長さ
  7940:         l -= s;
  7941:         if (true) {
  7942:           for (s -= 16; s >= 0; s -= 16) {
  7943:             bb[o     ] = mmd.mmdRbs (a     );
  7944:             bb[o +  1] = mmd.mmdRbs (a +  1);
  7945:             bb[o +  2] = mmd.mmdRbs (a +  2);
  7946:             bb[o +  3] = mmd.mmdRbs (a +  3);
  7947:             bb[o +  4] = mmd.mmdRbs (a +  4);
  7948:             bb[o +  5] = mmd.mmdRbs (a +  5);
  7949:             bb[o +  6] = mmd.mmdRbs (a +  6);
  7950:             bb[o +  7] = mmd.mmdRbs (a +  7);
  7951:             bb[o +  8] = mmd.mmdRbs (a +  8);
  7952:             bb[o +  9] = mmd.mmdRbs (a +  9);
  7953:             bb[o + 10] = mmd.mmdRbs (a + 10);
  7954:             bb[o + 11] = mmd.mmdRbs (a + 11);
  7955:             bb[o + 12] = mmd.mmdRbs (a + 12);
  7956:             bb[o + 13] = mmd.mmdRbs (a + 13);
  7957:             bb[o + 14] = mmd.mmdRbs (a + 14);
  7958:             bb[o + 15] = mmd.mmdRbs (a + 15);
  7959:             a += 16;
  7960:             o += 16;
  7961:           }
  7962:           s += 16;
  7963:         }
  7964:         for (int i = 0; i < s; i++) {
  7965:           bb[o + i] = mmd.mmdRbs (a + i);
  7966:         }
  7967:         a += s;
  7968:         o += s;
  7969:         r = BUS_PAGE_SIZE;
  7970:       }
  7971:     }
  7972:   }  //busRbb(int,byte[],int,int)
  7973: 
  7974:   //busWbb (a, bb, o, l)
  7975:   //  ライトバイトバッファ
  7976:   public static void busWbb (int a, byte[] bb, int o, int l) throws M68kException {
  7977:     if (false) {
  7978:       for (int i = 0; i < l; i++) {
  7979:         int ai = a + i;
  7980:         if (DataBreakPoint.DBP_ON) {
  7981:           DataBreakPoint.dbpMemoryMap[ai >>> BUS_PAGE_BITS].mmdWb (ai, bb[o + i]);
  7982:         } else {
  7983:           busMemoryMap[ai >>> BUS_PAGE_BITS].mmdWb (ai, bb[o + i]);
  7984:         }
  7985:       }
  7986:     } else {
  7987:       int r = (~a & BUS_PAGE_SIZE - 1) + 1;  //最初のページの残りの長さ。1~BUS_PAGE_SIZE
  7988:       while (l > 0) {
  7989:         MemoryMappedDevice mmd;
  7990:         if (DataBreakPoint.DBP_ON) {
  7991:           mmd = DataBreakPoint.dbpMemoryMap[a >>> BUS_PAGE_BITS];  //ページのデバイス
  7992:         } else {
  7993:           mmd = busMemoryMap[a >>> BUS_PAGE_BITS];  //ページのデバイス
  7994:         }
  7995:         int s = l <= r ? l : r;  //このページで転送する長さ
  7996:         l -= s;
  7997:         if (true) {
  7998:           for (s -= 16; s >= 0; s -= 16) {
  7999:             mmd.mmdWb (a     , bb[o     ]);
  8000:             mmd.mmdWb (a +  1, bb[o +  1]);
  8001:             mmd.mmdWb (a +  2, bb[o +  2]);
  8002:             mmd.mmdWb (a +  3, bb[o +  3]);
  8003:             mmd.mmdWb (a +  4, bb[o +  4]);
  8004:             mmd.mmdWb (a +  5, bb[o +  5]);
  8005:             mmd.mmdWb (a +  6, bb[o +  6]);
  8006:             mmd.mmdWb (a +  7, bb[o +  7]);
  8007:             mmd.mmdWb (a +  8, bb[o +  8]);
  8008:             mmd.mmdWb (a +  9, bb[o +  9]);
  8009:             mmd.mmdWb (a + 10, bb[o + 10]);
  8010:             mmd.mmdWb (a + 11, bb[o + 11]);
  8011:             mmd.mmdWb (a + 12, bb[o + 12]);
  8012:             mmd.mmdWb (a + 13, bb[o + 13]);
  8013:             mmd.mmdWb (a + 14, bb[o + 14]);
  8014:             mmd.mmdWb (a + 15, bb[o + 15]);
  8015:             a += 16;
  8016:             o += 16;
  8017:           }
  8018:           s += 16;
  8019:         }
  8020:         for (int i = 0; i < s; i++) {
  8021:           mmd.mmdWb (a + i, bb[o + i]);
  8022:         }
  8023:         a += s;
  8024:         o += s;
  8025:         r = BUS_PAGE_SIZE;
  8026:       }
  8027:     }
  8028:   }  //busWbb(int,byte[],int,int)
  8029: 
  8030:   //busVb (a, d)
  8031:   //  ライトバイト(エラーなし)
  8032:   public static void busVb (int a, int d) {
  8033:     try {
  8034:       if (DataBreakPoint.DBP_ON) {
  8035:         (regSRS != 0 ? busSuperMap : busUserMap)[a >>> BUS_PAGE_BITS].mmdWb (a, d);
  8036:       } else {
  8037:         busMemoryMap[a >>> BUS_PAGE_BITS].mmdWb (a, d);
  8038:       }
  8039:     } catch (M68kException e) {
  8040:     }
  8041:   }  //busVb(int,int)
  8042: 
  8043:   //busVw (a, d)
  8044:   //  ライトワード(エラーなし)
  8045:   public static void busVw (int a, int d) {
  8046:     try {
  8047:       if (TEST_BIT_0_SHIFT ? a << 31 - 0 >= 0 : (a & 1) == 0) {  //偶数
  8048:         if (DataBreakPoint.DBP_ON) {
  8049:           (regSRS != 0 ? busSuperMap : busUserMap)[a >>> BUS_PAGE_BITS].mmdWw (a, d);
  8050:         } else {
  8051:           busMemoryMap[a >>> BUS_PAGE_BITS].mmdWw (a, d);
  8052:         }
  8053:       }
  8054:     } catch (M68kException e) {
  8055:     }
  8056:   }  //busVw(int,int)
  8057: 
  8058:   //busVl (a, d)
  8059:   //  ライトロング(エラーなし)
  8060:   public static void busVl (int a, int d) {
  8061:     try {
  8062:       if (TEST_BIT_0_SHIFT && TEST_BIT_1_SHIFT ? a << 30 == 0 : (a & 3) == 0) {  //4の倍数
  8063:         if (DataBreakPoint.DBP_ON) {
  8064:           (regSRS != 0 ? busSuperMap : busUserMap)[a >>> BUS_PAGE_BITS].mmdWl (a, d);
  8065:         } else {
  8066:           busMemoryMap[a >>> BUS_PAGE_BITS].mmdWl (a, d);
  8067:         }
  8068:       } else if (TEST_BIT_0_SHIFT ? a << 31 - 0 >= 0 : (a & 1) == 0) {  //4の倍数ではない偶数
  8069:         int a2 = a + 2;
  8070:         MemoryMappedDevice mmd;
  8071:         MemoryMappedDevice mmd2;
  8072:         if (DataBreakPoint.DBP_ON) {
  8073:           mmd = (regSRS != 0 ? busSuperMap : busUserMap)[a >>> BUS_PAGE_BITS];
  8074:           mmd2 = (regSRS != 0 ? busSuperMap : busUserMap)[a2 >>> BUS_PAGE_BITS];
  8075:         } else {
  8076:           mmd = busMemoryMap[a >>> BUS_PAGE_BITS];
  8077:           mmd2 = busMemoryMap[a2 >>> BUS_PAGE_BITS];
  8078:         }
  8079:         if (mmd == mmd2) {  //4の倍数ではない偶数でデバイスを跨がない
  8080:           mmd.mmdWl (a, d);
  8081:         } else {  //4の倍数ではない偶数でデバイスを跨ぐ
  8082:           mmd.mmdWw (a, d >> 16);
  8083:           mmd2.mmdWw (a2, d);
  8084:         }
  8085:       }
  8086:     } catch (M68kException e) {
  8087:     }
  8088:   }  //busVl(int,int)
  8089: 
  8090: 
  8091: 
  8092:   //========================================================================================
  8093:   //$$GRA グラフィック画面
  8094:   //  512ドットのときハードウェアスクロールが常に4ページあるのでメモリモードに関わらず4ビットゼロ拡張で格納する
  8095:   //  偶数アドレスの8ビット全部と奇数アドレスの上位4ビットは常に0
  8096:   //
  8097:   //  512ドット16色
  8098:   //                アドレス             アクセス                  格納
  8099:   //    GE0  0x00c00000~0x00c7ffff  ............3210  ──  ............3210
  8100:   //    GE1  0x00c80000~0x00cfffff  ............7654  ──  ............7654
  8101:   //    GE2  0x00d00000~0x00d7ffff  ............ba98  ──  ............ba98
  8102:   //    GE3  0x00d80000~0x00dfffff  ............fedc  ──  ............fedc
  8103:   //
  8104:   //  512ドット256色
  8105:   //                アドレス             アクセス                  格納
  8106:   //    GF0  0x00c00000~0x00c7ffff  ........76543210  ─┬  ............3210
  8107:   //    GF1  0x00c80000~0x00cfffff  ........fedcba98  ┐└  ............7654
  8108:   //         0x00d00000~0x00d7ffff                    ├─  ............ba98
  8109:   //         0x00d80000~0x00dfffff                    └─  ............fedc
  8110:   //
  8111:   //  512ドット65536色
  8112:   //                アドレス             アクセス                  格納
  8113:   //    GG0  0x00c00000~0x00c7ffff  fedcba9876543210  ─┬  ............3210
  8114:   //         0x00c80000~0x00cfffff                      ├  ............7654
  8115:   //         0x00d00000~0x00d7ffff                      ├  ............ba98
  8116:   //         0x00d80000~0x00dfffff                      └  ............fedc
  8117:   //
  8118:   //  1024ドット16色
  8119:   //                アドレス             アクセス                  格納
  8120:   //    GH0  0x00c00000~0x00dfffff  ............3210  ──  ............3210
  8121:   //
  8122: 
  8123: 
  8124: 
  8125:     //graInit ()
  8126:     public static void graInit () {
  8127:     }
  8128: 
  8129: 
  8130: 
  8131:   //========================================================================================
  8132:   //$$TXT テキスト画面
  8133: 
  8134:   //txtInit ()
  8135:   //  テキスト画面の初期化
  8136:   public static void txtInit () {
  8137:   }  //txtInit()
  8138: 
  8139: 
  8140: 
  8141:   //========================================================================================
  8142:   //$$SVS スーパーバイザ領域設定
  8143:   public static final int SVS_AREASET = 0x00e86001;  //0x00 0x00000000~0x00002000
  8144:   //                                                      0x01 0x00000000~0x00004000
  8145:   //                                                      0x02 0x00000000~0x00008000
  8146:   //                                                      0x04 0x00000000~0x00010000
  8147:   //                                                      0x08 0x00000000~0x00020000
  8148:   //                                                      0x10 0x00000000~0x00040000
  8149:   //                                                      0x20 0x00000000~0x00080000
  8150:   //                                                      0x40 0x00000000~0x00100000
  8151:   //                                                      0x80 0x00000000~0x00200000
  8152: 
  8153:   public static void svsInit () {
  8154:   }
  8155: 
  8156: 
  8157: 
  8158:   //========================================================================================
  8159:   //$$SYS システムポート
  8160:   //
  8161:   //     アドレス   bit  RW  名前   X68030
  8162:   //    0x00e8e001  0-3  RW           13    コントラスト(0=最も暗い,15=最も明るい)
  8163:   //    0x00e8e003   3   R             1    TV ON/OFFステータス(0=ON,1=OFF)
  8164:   //                      W                 TVリモコン信号
  8165:   //                 2   R   FIELD     0
  8166:   //                 1   RW  3D-L      0    (3Dスコープ)シャッター左(0=CLOSE,1=OPEN)
  8167:   //                 0   RW  3D-R      0    (3Dスコープ)シャッター右(0=CLOSE,1=OPEN)
  8168:   //    0x00e8e005  4-0   W                 (カラーイメージユニット(デジタイズテロッパ))画像入力コントロール
  8169:   //                                          bit4  IMAGE IN bit17
  8170:   //                                          bit3  IMAGE IN bit18
  8171:   //                                          bit2  IMAGE IN bit19
  8172:   //                                          bit1  IMAGE IN bit20
  8173:   //                                          bit0  IMAGE IN bit21
  8174:   //    0x00e8e007   3   R             1    キージャックステータス(0=抜かれている,1=差し込まれている)
  8175:   //                      W                 キーレディ(0=キーデータ送信禁止,1=キーデータ送信許可)
  8176:   //                 2    W            1    1=NMIリセット
  8177:   //                 1   RW            0    HRL。詳細はCRTCを参照
  8178:   //                 0   RW            0    (現在は使用されていない)解像度LED(0=消灯,1=点灯)
  8179:   //    0x00e8e009  7-4   W                 (X68030のみ)ROMアクセスウェイト
  8180:   //                3-0   W                 (X68030のみ)RAMアクセスウェイト(0=25MHz,4=16MHz相当,10=10MHz相当)
  8181:   //    0x00e8e00b  7-4  R            13    機種(13=MC68030,15=MC68000)
  8182:   //                3-0  R            12    動作周波数(12=25MHz,14=16MHz,15=10MHz)
  8183:   //    0x00e8e00d  7-0   W                 SRAM WRITE ENABLE(49=SRAM書き込み可)
  8184:   //    0x00e8e00f  3-0   W                 フロント電源スイッチがOFFになっているとき0→15→15で電源OFF
  8185:   //
  8186:   //    未定義のbitはリードすると1、ライトしてもバスエラーは発生しない
  8187:   //    アドレスのbit12-4はデコードされない。0x00e8e000~0x00e8ffffの範囲に16バイトのポートが512回繰り返し現れる
  8188:   //
  8189: 
  8190:   public static boolean sysNMIFlag;  //true=INTERRUPTスイッチが押された
  8191: 
  8192:   //sysInit ()
  8193:   //  初期化
  8194:   public static void sysInit () {
  8195:     sysNMIFlag = false;
  8196:   }  //sysInit()
  8197: 
  8198:   //割り込み受付
  8199:   //  コアが割り込み要求を受け付けたときに呼び出す
  8200:   //  割り込みベクタ番号を返す
  8201:   //  割り込み要求を取り下げる場合は0を返す
  8202:   //  オートベクタを使用するデバイスはオートベクタの番号を返すこと
  8203:   public static int sysAcknowledge () {
  8204:     return M68kException.M6E_LEVEL_7_INTERRUPT_AUTOVECTOR;
  8205:   }  //sysAcknowledge()
  8206: 
  8207:   //割り込み終了
  8208:   //  コアが割り込み処理を終了したときに呼び出す
  8209:   //  まだ処理されていない割り込みが残っていたら再度割り込み要求を出す
  8210:   public static void sysDone () {
  8211:     if (sysNMIFlag) {  //NMIリセットされていない
  8212:       mpuIRR |= MPU_SYS_INTERRUPT_MASK;
  8213:     }
  8214:   }  //sysDone()
  8215: 
  8216:   //sysInterrupt ()
  8217:   //  INTERRUPTスイッチが押された
  8218:   public static void sysInterrupt () {
  8219:     sysNMIFlag = true;
  8220:     mpuIRR |= MPU_SYS_INTERRUPT_MASK;
  8221:   }  //sysInterrupt()
  8222: 
  8223:   //sysResetNMI ()
  8224:   //  NMIリセット
  8225:   public static void sysResetNMI () {
  8226:     sysNMIFlag = false;
  8227:   }  //sysResetNMI()
  8228: 
  8229: 
  8230: 
  8231:   //========================================================================================
  8232:   //$$EB2 拡張ボードレベル2割り込み
  8233: 
  8234:   public static final int EB2_SPC_REQUEST = 0x4000;  //拡張SCSI
  8235:   public static final int EB2_SPC_VECTOR = 0xf6;  //拡張SCSI
  8236: 
  8237:   //割り込み要求
  8238:   //  0b00010000_00000000  SPC割り込み要求あり
  8239:   public static int eb2Request;  //割り込み要求。デバイスは操作しないこと
  8240: 
  8241:   //eb2Reset ()
  8242:   //  拡張ボードレベル2割り込みをリセットする
  8243:   public static void eb2Reset () {
  8244:     eb2Request = 0;
  8245:   }  //eb2Reset()
  8246: 
  8247:   //eb2Interrupt (mask)
  8248:   //  割り込み要求
  8249:   //  デバイスが割り込みを要求するときに呼び出す
  8250:   //  mask  EB2_SPC_VECTOR  拡張SCSI割り込みを要求する
  8251:   public static void eb2Interrupt (int mask) {
  8252:     eb2Request |= mask;
  8253:     mpuIRR |= MPU_EB2_INTERRUPT_MASK;
  8254:   }  //eb2Interrupt(int)
  8255: 
  8256:   //vector = eb2Acknowledge ()
  8257:   //  割り込み受付
  8258:   //  コアが割り込み要求を受け付けたときに呼び出す
  8259:   //  割り込みベクタ番号を返す
  8260:   //  割り込み要求を取り下げる場合は0を返す
  8261:   //  オートベクタを使用するデバイスはオートベクタの番号を返すこと
  8262:   public static int eb2Acknowledge () {
  8263:     if ((eb2Request & EB2_SPC_REQUEST) != 0) {
  8264:       eb2Request &= ~EB2_SPC_REQUEST;
  8265:       return EB2_SPC_VECTOR;
  8266:     }
  8267:     return 0;
  8268:   }  //eb2Acknowledge()
  8269: 
  8270:   //eb2Done ()
  8271:   //  割り込み終了
  8272:   //  コアが割り込み処理を終了したときに呼び出す
  8273:   //  まだ処理されていない割り込みが残っていたら再度割り込み要求を出す
  8274:   public static void eb2Done () {
  8275:     if (eb2Request != 0) {
  8276:       mpuIRR |= MPU_EB2_INTERRUPT_MASK;
  8277:     }
  8278:   }  //eb2Done()
  8279: 
  8280: 
  8281: 
  8282:   //========================================================================================
  8283:   //TGA ツクモグラフィックアクセラレータPCMボード
  8284:   //  0x00e9e200  ツクモグラフィックアクセラレータPCMボード(TS-6BGA)
  8285:   //! 非対応
  8286: 
  8287: 
  8288: 
  8289:   //========================================================================================
  8290:   //WIN WINDRV
  8291:   //  0x00e9f000  040Excel
  8292:   //  0x00e9f000  WINDRV
  8293:   //! 非対応
  8294: 
  8295: 
  8296: 
  8297:   //========================================================================================
  8298:   //$$EXS 拡張SCSI
  8299:   //  内蔵SCSIと共通
  8300: 
  8301: 
  8302: 
  8303:   //========================================================================================
  8304:   //$$XB2 拡張ボード領域2
  8305:   //  0x00eaf900  FAXボード(CZ-6BC1)
  8306:   //  0x00eafa00  MIDIボード(CZ-6BM1)
  8307:   //  0x00eafb00  パラレルボード(CZ-6BN1)
  8308:   //  0x00eafc00  RS-232Cボード(CZ-6BF1)
  8309:   //  0x00eafd00  ユニバーサルI/Oボード(CZ-6BU1)
  8310:   //  0x00eafe00  GP-IBボード(CZ-6BG1)
  8311:   //  0x00eaff00  スーパーバイザエリア設定
  8312:   //
  8313:   //  スーパーバイザエリア設定のみ対応
  8314: 
  8315:   //スーパーバイザエリア設定ポート
  8316:   //  0x00eaff81  bit0  0x00200000~0x0023ffff
  8317:   //              bit1  0x00240000~0x0027ffff
  8318:   //              bit2  0x00280000~0x002bffff
  8319:   //              bit3  0x002c0000~0x002fffff
  8320:   //              bit4  0x00300000~0x0033ffff
  8321:   //              bit5  0x00340000~0x0037ffff
  8322:   //              bit6  0x00380000~0x003bffff
  8323:   //              bit7  0x003c0000~0x003fffff
  8324:   //  0x00eaff83  bit0  0x00400000~0x0043ffff
  8325:   //              bit1  0x00440000~0x0047ffff
  8326:   //              bit2  0x00480000~0x004bffff
  8327:   //              bit3  0x004c0000~0x004fffff
  8328:   //              bit4  0x00500000~0x0053ffff
  8329:   //              bit5  0x00540000~0x0057ffff
  8330:   //              bit6  0x00580000~0x005bffff
  8331:   //              bit7  0x005c0000~0x005fffff
  8332:   //  0x00eaff85  bit0  0x00600000~0x0063ffff
  8333:   //              bit1  0x00640000~0x0067ffff
  8334:   //              bit2  0x00680000~0x006bffff
  8335:   //              bit3  0x006c0000~0x006fffff
  8336:   //              bit4  0x00700000~0x0073ffff
  8337:   //              bit5  0x00740000~0x0077ffff
  8338:   //              bit6  0x00780000~0x007bffff
  8339:   //              bit7  0x007c0000~0x007fffff
  8340:   //  0x00eaff87  bit0  0x00800000~0x0083ffff
  8341:   //              bit1  0x00840000~0x0087ffff
  8342:   //              bit2  0x00880000~0x008bffff
  8343:   //              bit3  0x008c0000~0x008fffff
  8344:   //              bit4  0x00900000~0x0093ffff
  8345:   //              bit5  0x00940000~0x0097ffff
  8346:   //              bit6  0x00980000~0x009bffff
  8347:   //              bit7  0x009c0000~0x009fffff
  8348:   //  0x00eaff89  bit0  0x00a00000~0x00a3ffff
  8349:   //              bit1  0x00a40000~0x00a7ffff
  8350:   //              bit2  0x00a80000~0x00abffff
  8351:   //              bit3  0x00ac0000~0x00afffff
  8352:   //              bit4  0x00b00000~0x00b3ffff
  8353:   //              bit5  0x00b40000~0x00b7ffff
  8354:   //              bit6  0x00b80000~0x00bbffff
  8355:   //              bit7  0x00bc0000~0x00bfffff
  8356: 
  8357: 
  8358: 
  8359:   //========================================================================================
  8360:   //$$BNK バンクメモリ
  8361:   //  $00EAFF7F  バンクメモリのページ番号。0~255
  8362:   //  $00EE0000~$00EFFFFF  バンクメモリ
  8363: 
  8364:   public static final int BNK_SIZE = 1024 * 1024 * 32;  //サイズ
  8365:   public static byte[] bnkMemory;  //メモリの配列
  8366:   public static int bnkPageStart;  //ページの先頭のインデックス。ページ番号<<17
  8367:   public static boolean bnkOn;  //true=バンクメモリが有効
  8368: 
  8369:   public static void bnkInit () {
  8370:     bnkMemory = new byte[BNK_SIZE];
  8371:     byte[] array = Settings.sgsGetData ("bankdata");
  8372:     if (array.length != 0) {
  8373:       System.arraycopy (array, 0, bnkMemory, 0, Math.min (array.length, BNK_SIZE));
  8374:     }
  8375:     bnkPageStart = 0;
  8376:     //bnkOn = true;
  8377:     bnkOn = false;
  8378:   }
  8379: 
  8380:   public static void bnkTini () {
  8381:     Settings.sgsPutData ("bankdata", bnkMemory, 0, BNK_SIZE);
  8382:   }
  8383: 
  8384: 
  8385: 
  8386:   //========================================================================================
  8387:   //$$FPU FPU
  8388: 
  8389:   //FPU/FPCP
  8390:   public static ExpressionEvaluator fpuMotherboardCoprocessor;  //マザーボードコプロセッサ
  8391:   public static ExpressionEvaluator fpuOnChipFPU;  //on-chip FPU
  8392:   public static ExpressionEvaluator fpuBox;  //浮動小数点命令を実行するFPU/FPCP
  8393: 
  8394:   //数値演算プロセッサボード
  8395:   public static EFPBox fpuCoproboard1;  //数値演算プロセッサボード1
  8396:   public static EFPBox fpuCoproboard2;  //数値演算プロセッサボード2
  8397: 
  8398:   //浮動小数点レジスタ
  8399:   public static EFPBox.EFP[] fpuFPn;
  8400: 
  8401:   //FPCR control register
  8402:   //  exception enable byte
  8403:   public static final int FPU_FPCR_BSUN   = 0b00000000_00000000_10000000_00000000;  //branch/set on unordered
  8404:   public static final int FPU_FPCR_SNAN   = 0b00000000_00000000_01000000_00000000;  //signaling not a number
  8405:   public static final int FPU_FPCR_OPERR  = 0b00000000_00000000_00100000_00000000;  //operand error
  8406:   public static final int FPU_FPCR_OVFL   = 0b00000000_00000000_00010000_00000000;  //overflow
  8407:   public static final int FPU_FPCR_UNFL   = 0b00000000_00000000_00001000_00000000;  //underflow
  8408:   public static final int FPU_FPCR_DZ     = 0b00000000_00000000_00000100_00000000;  //divide by zero
  8409:   public static final int FPU_FPCR_INEX2  = 0b00000000_00000000_00000010_00000000;  //inexact operation
  8410:   public static final int FPU_FPCR_INEX1  = 0b00000000_00000000_00000001_00000000;  //inexact decimal input
  8411:   //  mode control byte
  8412:   //    rounding precision
  8413:   public static final int FPU_FPCR_PE     = 0b00000000_00000000_00000000_00000000;  //extended
  8414:   public static final int FPU_FPCR_PS     = 0b00000000_00000000_00000000_01000000;  //single
  8415:   public static final int FPU_FPCR_PD     = 0b00000000_00000000_00000000_10000000;  //double
  8416:   //    rounding mode
  8417:   public static final int FPU_FPCR_RN     = 0b00000000_00000000_00000000_00000000;  //to nearest
  8418:   public static final int FPU_FPCR_RZ     = 0b00000000_00000000_00000000_00010000;  //toward zero
  8419:   public static final int FPU_FPCR_RM     = 0b00000000_00000000_00000000_00100000;  //toward minus infinity
  8420:   public static final int FPU_FPCR_RP     = 0b00000000_00000000_00000000_00110000;  //toward plus infinity
  8421: 
  8422:   //FPSR status register
  8423:   //  condition code byte
  8424:   public static final int FPU_FPSR_N         = 0b00001000_00000000_00000000_00000000;  //negative
  8425:   public static final int FPU_FPSR_Z         = 0b00000100_00000000_00000000_00000000;  //zero
  8426:   public static final int FPU_FPSR_I         = 0b00000010_00000000_00000000_00000000;  //infinity
  8427:   public static final int FPU_FPSR_NAN       = 0b00000001_00000000_00000000_00000000;  //not a number or unordered
  8428:   //  quotient byte
  8429:   public static final int FPU_FPSR_S         = 0b00000000_10000000_00000000_00000000;  //sign of quotient
  8430:   public static final int FPU_FPSR_QUOTIENT  = 0b00000000_01111111_00000000_00000000;  //quotient
  8431:   //  exception status byte
  8432:   public static final int FPU_FPSR_EXC_BSUN  = 0b00000000_00000000_10000000_00000000;  //branch/set on unordered
  8433:   public static final int FPU_FPSR_EXC_SNAN  = 0b00000000_00000000_01000000_00000000;  //signaling not a number
  8434:   public static final int FPU_FPSR_EXC_OPERR = 0b00000000_00000000_00100000_00000000;  //operand error
  8435:   public static final int FPU_FPSR_EXC_OVFL  = 0b00000000_00000000_00010000_00000000;  //overflow
  8436:   public static final int FPU_FPSR_EXC_UNFL  = 0b00000000_00000000_00001000_00000000;  //underflow
  8437:   public static final int FPU_FPSR_EXC_DZ    = 0b00000000_00000000_00000100_00000000;  //divide by zero
  8438:   public static final int FPU_FPSR_EXC_INEX2 = 0b00000000_00000000_00000010_00000000;  //inexact operation
  8439:   public static final int FPU_FPSR_EXC_INEX1 = 0b00000000_00000000_00000001_00000000;  //inexact decimal input
  8440:   //  accrued exception byte
  8441:   public static final int FPU_FPSR_AEXC_IOP  = 0b00000000_00000000_00000000_10000000;  //invalid operation
  8442:   public static final int FPU_FPSR_AEXC_OVFL = 0b00000000_00000000_00000000_01000000;  //overflow
  8443:   public static final int FPU_FPSR_AEXC_UNFL = 0b00000000_00000000_00000000_00100000;  //underflow
  8444:   public static final int FPU_FPSR_AEXC_DZ   = 0b00000000_00000000_00000000_00010000;  //divide by zero
  8445:   public static final int FPU_FPSR_AEXC_INEX = 0b00000000_00000000_00000000_00001000;  //inexact
  8446: 
  8447:   //  EXCからAEXCへの変換
  8448:   //    AEXC_IOP |= EXC_BSUN | EXC_SNAN | EXC_OPERR
  8449:   //    AEXC_OVFL |= EXC_OVFL
  8450:   //    AEXC_UNFL |= EXC_UNFL & EXC_INEX2
  8451:   //    AEXC_DZ |= EXC_DZ
  8452:   //    AEXC_INEX |= EXC_OVFL | EXC_INEX2 | EXC_INEX1
  8453:   public static final int[] FPU_FPSR_EXC_TO_AEXC = new int[256];
  8454: 
  8455:   //コンディション
  8456:   //
  8457:   //  fpsrのbit27-24
  8458:   //    MZIN
  8459:   //    0000  0<x
  8460:   //    0001  NaN
  8461:   //    0010  +Inf
  8462:   //    0100  +0
  8463:   //    1000  x<0
  8464:   //    1010  -Inf
  8465:   //    1100  -0
  8466:   //
  8467:   //  FPU_CCMAP_882[(オペコードまたは拡張ワード&63)<<4|fpsr>>24&15]==trueならば条件成立
  8468:   //  FPU_CCMAP_060[(オペコードまたは拡張ワード&63)<<4|fpsr>>24&15]==trueならば条件成立
  8469:   //
  8470:   //  MC68882とMC68060ではOR,NE,GLE,SNEの条件が異なる
  8471: 
  8472:   //MC68882
  8473:   //  perl -e "@a=();for$a(0..15){$m=$a>>3&1;$z=$a>>2&1;$n=$a&1;@b=map{$_&1}(0,$z,~($n|$z|$m),$z|~($n|$m),$m&~($n|$z),$z|($m&~$n),~($n|$z),$z|~$n,$n,$n|$z,$n|~($m|$z),$n|($z|~$m),$n|($m&~$z),$n|$z|$m,$n|~$z,1);push@a,@b,@b,@b,@b}for$y(0..63){print'    ';$t=0;for$x(0..15){$c=$a[$x<<6|$y];$t=($t<<1)+$c;print(($c?'T':'F').',');}printf'  //%04x %06b%c',$t,$y,10;}
  8474:   //
  8475:   //F,F,F,F,F,F,F,F,T,T,T,T,T,T,T,T,  //N
  8476:   //F,F,F,F,T,T,T,T,F,F,F,F,T,T,T,T,  //Z
  8477:   //F,T,F,T,F,T,F,T,F,T,F,T,F,T,F,T,  //NAN
  8478:   public static final boolean[] FPU_CCMAP_882 = {
  8479:     //                                       cccccc  cc    等式          意味
  8480:     //IEEEアウェアテスト
  8481:     F,F,F,F,F,F,F,F,F,F,F,F,F,F,F,F,  //0000 000000  F     0             偽
  8482:     F,F,F,F,T,T,T,T,F,F,F,F,T,T,T,T,  //0f0f 000001  EQ    Z             等しい
  8483:     T,F,T,F,F,F,F,F,F,F,F,F,F,F,F,F,  //a000 000010  OGT   ~(NAN|Z|N)    比較可能でより大きい
  8484:     T,F,T,F,T,T,T,T,F,F,F,F,T,T,T,T,  //af0f 000011  OGE   Z|~(NAN|N)    等しいか比較可能でより大きい
  8485:     F,F,F,F,F,F,F,F,T,F,T,F,F,F,F,F,  //00a0 000100  OLT   N&~(NAN|Z)    比較可能でより小さい
  8486:     F,F,F,F,T,T,T,T,T,F,T,F,T,T,T,T,  //0faf 000101  OLE   Z|(N&~NAN)    等しいか比較可能でより小さい
  8487:     T,F,T,F,F,F,F,F,T,F,T,F,F,F,F,F,  //a0a0 000110  OGL   ~(NAN|Z)      比較可能で等しくない
  8488:     T,F,T,F,T,T,T,T,T,F,T,F,T,T,T,T,  //afaf 000111  OR    Z|~NAN        等しいか比較可能
  8489:     F,T,F,T,F,T,F,T,F,T,F,T,F,T,F,T,  //5555 001000  UN    NAN           比較不能
  8490:     F,T,F,T,T,T,T,T,F,T,F,T,T,T,T,T,  //5f5f 001001  UEQ   NAN|Z         比較不能か等しい
  8491:     T,T,T,T,F,T,F,T,F,T,F,T,F,T,F,T,  //f555 001010  UGT   NAN|~(N|Z)    比較不能かより大きい
  8492:     T,T,T,T,T,T,T,T,F,T,F,T,T,T,T,T,  //ff5f 001011  UGE   NAN|(Z|~N)    比較不能かより大きいか等しい
  8493:     F,T,F,T,F,T,F,T,T,T,T,T,F,T,F,T,  //55f5 001100  ULT   NAN|(N&~Z)    比較不能かより小さい
  8494:     F,T,F,T,T,T,T,T,T,T,T,T,T,T,T,T,  //5fff 001101  ULE   NAN|Z|N       比較不能かより小さいか等しい
  8495:     T,T,T,T,F,T,F,T,T,T,T,T,F,T,F,T,  //f5f5 001110  NE    NAN|~Z        比較不能か等しくない
  8496:     T,T,T,T,T,T,T,T,T,T,T,T,T,T,T,T,  //ffff 001111  T     1             真
  8497:     //IEEEノンアウェアテスト
  8498:     //  NANがセットされているとき、FPSRのBSUNがセットされ、許可されていれば例外が発生する
  8499:     F,F,F,F,F,F,F,F,F,F,F,F,F,F,F,F,  //0000 010000  SF    0             偽(シグナリング)
  8500:     F,F,F,F,T,T,T,T,F,F,F,F,T,T,T,T,  //0f0f 010001  SEQ   Z             等しい(シグナリング)
  8501:     T,F,T,F,F,F,F,F,F,F,F,F,F,F,F,F,  //a000 010010  GT    ~(NAN|Z|N)    より大きい
  8502:     T,F,T,F,T,T,T,T,F,F,F,F,T,T,T,T,  //af0f 010011  GE    Z|~(NAN|N)    より大きいか等しい
  8503:     F,F,F,F,F,F,F,F,T,F,T,F,F,F,F,F,  //00a0 010100  LT    N&~(NAN|Z)    より小さい
  8504:     F,F,F,F,T,T,T,T,T,F,T,F,T,T,T,T,  //0faf 010101  LE    Z|(N&~NAN)    より小さいか等しい
  8505:     T,F,T,F,F,F,F,F,T,F,T,F,F,F,F,F,  //a0a0 010110  GL    ~(NAN|Z)      等しくない
  8506:     T,F,T,F,T,T,T,T,T,F,T,F,T,T,T,T,  //afaf 010111  GLE   Z|~NAN        より大きいか小さいか等しい
  8507:     F,T,F,T,F,T,F,T,F,T,F,T,F,T,F,T,  //5555 011000  NGLE  NAN           GLEでない
  8508:     F,T,F,T,T,T,T,T,F,T,F,T,T,T,T,T,  //5f5f 011001  NGL   NAN|Z         GLでない
  8509:     T,T,T,T,F,T,F,T,F,T,F,T,F,T,F,T,  //f555 011010  NLE   NAN|~(N|Z)    LEでない
  8510:     T,T,T,T,T,T,T,T,F,T,F,T,T,T,T,T,  //ff5f 011011  NLT   NAN|(Z|~N)    LTでない
  8511:     F,T,F,T,F,T,F,T,T,T,T,T,F,T,F,T,  //55f5 011100  NGE   NAN|(N&~Z)    GEでない
  8512:     F,T,F,T,T,T,T,T,T,T,T,T,T,T,T,T,  //5fff 011101  NGT   NAN|Z|N       GTでない
  8513:     T,T,T,T,F,T,F,T,T,T,T,T,F,T,F,T,  //f5f5 011110  SNE   NAN|~Z        等しくない(シグナリング)
  8514:     T,T,T,T,T,T,T,T,T,T,T,T,T,T,T,T,  //ffff 011111  ST    1             真(シグナリング)
  8515:     //
  8516:     F,F,F,F,F,F,F,F,F,F,F,F,F,F,F,F,  //0000 100000
  8517:     F,F,F,F,T,T,T,T,F,F,F,F,T,T,T,T,  //0f0f 100001
  8518:     T,F,T,F,F,F,F,F,F,F,F,F,F,F,F,F,  //a000 100010
  8519:     T,F,T,F,T,T,T,T,F,F,F,F,T,T,T,T,  //af0f 100011
  8520:     F,F,F,F,F,F,F,F,T,F,T,F,F,F,F,F,  //00a0 100100
  8521:     F,F,F,F,T,T,T,T,T,F,T,F,T,T,T,T,  //0faf 100101
  8522:     T,F,T,F,F,F,F,F,T,F,T,F,F,F,F,F,  //a0a0 100110
  8523:     T,F,T,F,T,T,T,T,T,F,T,F,T,T,T,T,  //afaf 100111
  8524:     F,T,F,T,F,T,F,T,F,T,F,T,F,T,F,T,  //5555 101000
  8525:     F,T,F,T,T,T,T,T,F,T,F,T,T,T,T,T,  //5f5f 101001
  8526:     T,T,T,T,F,T,F,T,F,T,F,T,F,T,F,T,  //f555 101010
  8527:     T,T,T,T,T,T,T,T,F,T,F,T,T,T,T,T,  //ff5f 101011
  8528:     F,T,F,T,F,T,F,T,T,T,T,T,F,T,F,T,  //55f5 101100
  8529:     F,T,F,T,T,T,T,T,T,T,T,T,T,T,T,T,  //5fff 101101
  8530:     T,T,T,T,F,T,F,T,T,T,T,T,F,T,F,T,  //f5f5 101110
  8531:     T,T,T,T,T,T,T,T,T,T,T,T,T,T,T,T,  //ffff 101111
  8532:     //
  8533:     F,F,F,F,F,F,F,F,F,F,F,F,F,F,F,F,  //0000 110000
  8534:     F,F,F,F,T,T,T,T,F,F,F,F,T,T,T,T,  //0f0f 110001
  8535:     T,F,T,F,F,F,F,F,F,F,F,F,F,F,F,F,  //a000 110010
  8536:     T,F,T,F,T,T,T,T,F,F,F,F,T,T,T,T,  //af0f 110011
  8537:     F,F,F,F,F,F,F,F,T,F,T,F,F,F,F,F,  //00a0 110100
  8538:     F,F,F,F,T,T,T,T,T,F,T,F,T,T,T,T,  //0faf 110101
  8539:     T,F,T,F,F,F,F,F,T,F,T,F,F,F,F,F,  //a0a0 110110
  8540:     T,F,T,F,T,T,T,T,T,F,T,F,T,T,T,T,  //afaf 110111
  8541:     F,T,F,T,F,T,F,T,F,T,F,T,F,T,F,T,  //5555 111000
  8542:     F,T,F,T,T,T,T,T,F,T,F,T,T,T,T,T,  //5f5f 111001
  8543:     T,T,T,T,F,T,F,T,F,T,F,T,F,T,F,T,  //f555 111010
  8544:     T,T,T,T,T,T,T,T,F,T,F,T,T,T,T,T,  //ff5f 111011
  8545:     F,T,F,T,F,T,F,T,T,T,T,T,F,T,F,T,  //55f5 111100
  8546:     F,T,F,T,T,T,T,T,T,T,T,T,T,T,T,T,  //5fff 111101
  8547:     T,T,T,T,F,T,F,T,T,T,T,T,F,T,F,T,  //f5f5 111110
  8548:     T,T,T,T,T,T,T,T,T,T,T,T,T,T,T,T,  //ffff 111111
  8549:   };
  8550: 
  8551:   //MC68060
  8552:   //  perl -e "@a=();for$a(0..15){$m=$a>>3&1;$z=$a>>2&1;$n=$a&1;@b=map{$_&1}(0,$z,~($n|$z|$m),$z|~($n|$m),$m&~($n|$z),$z|($m&~$n),~($n|$z),~$n,$n,$n|$z,$n|~($m|$z),$n|($z|~$m),$n|($m&~$z),$n|$z|$m,~$z,1);push@a,@b,@b,@b,@b}for$y(0..63){print'    ';$t=0;for$x(0..15){$c=$a[$x<<6|$y];$t=($t<<1)+$c;print(($c?'T':'F').',');}printf'  //%04x %06b%c',$t,$y,10;}
  8553:   //
  8554:   //F,F,F,F,F,F,F,F,T,T,T,T,T,T,T,T,  //N
  8555:   //F,F,F,F,T,T,T,T,F,F,F,F,T,T,T,T,  //Z
  8556:   //F,T,F,T,F,T,F,T,F,T,F,T,F,T,F,T,  //NAN
  8557:   public static final boolean[] FPU_CCMAP_060 = {
  8558:     //                                       cccccc  cc    等式          意味
  8559:     //IEEEアウェアテスト
  8560:     F,F,F,F,F,F,F,F,F,F,F,F,F,F,F,F,  //0000 000000  F     0             偽
  8561:     F,F,F,F,T,T,T,T,F,F,F,F,T,T,T,T,  //0f0f 000001  EQ    Z             等しい
  8562:     T,F,T,F,F,F,F,F,F,F,F,F,F,F,F,F,  //a000 000010  OGT   ~(NAN|Z|N)    比較可能でより大きい
  8563:     T,F,T,F,T,T,T,T,F,F,F,F,T,T,T,T,  //af0f 000011  OGE   Z|~(NAN|N)    等しいか比較可能でより大きい
  8564:     F,F,F,F,F,F,F,F,T,F,T,F,F,F,F,F,  //00a0 000100  OLT   N&~(NAN|Z)    比較可能でより小さい
  8565:     F,F,F,F,T,T,T,T,T,F,T,F,T,T,T,T,  //0faf 000101  OLE   Z|(N&~NAN)    等しいか比較可能でより小さい
  8566:     T,F,T,F,F,F,F,F,T,F,T,F,F,F,F,F,  //a0a0 000110  OGL   ~(NAN|Z)      比較可能で等しくない
  8567:     T,F,T,F,T,F,T,F,T,F,T,F,T,F,T,F,  //aaaa 000111  OR    ~NAN          比較可能
  8568:     F,T,F,T,F,T,F,T,F,T,F,T,F,T,F,T,  //5555 001000  UN    NAN           比較不能
  8569:     F,T,F,T,T,T,T,T,F,T,F,T,T,T,T,T,  //5f5f 001001  UEQ   NAN|Z         比較不能か等しい
  8570:     T,T,T,T,F,T,F,T,F,T,F,T,F,T,F,T,  //f555 001010  UGT   NAN|~(N|Z)    比較不能かより大きい
  8571:     T,T,T,T,T,T,T,T,F,T,F,T,T,T,T,T,  //ff5f 001011  UGE   NAN|(Z|~N)    比較不能かより大きいか等しい
  8572:     F,T,F,T,F,T,F,T,T,T,T,T,F,T,F,T,  //55f5 001100  ULT   NAN|(N&~Z)    比較不能かより小さい
  8573:     F,T,F,T,T,T,T,T,T,T,T,T,T,T,T,T,  //5fff 001101  ULE   NAN|Z|N       比較不能かより小さいか等しい
  8574:     T,T,T,T,F,F,F,F,T,T,T,T,F,F,F,F,  //f0f0 001110  NE    ~Z            等しくない
  8575:     T,T,T,T,T,T,T,T,T,T,T,T,T,T,T,T,  //ffff 001111  T     1             真
  8576:     //IEEEノンアウェアテスト
  8577:     //  NANがセットされているとき、FPSRのBSUNがセットされ、許可されていれば例外が発生する
  8578:     F,F,F,F,F,F,F,F,F,F,F,F,F,F,F,F,  //0000 010000  SF    0             偽(シグナリング)
  8579:     F,F,F,F,T,T,T,T,F,F,F,F,T,T,T,T,  //0f0f 010001  SEQ   Z             等しい(シグナリング)
  8580:     T,F,T,F,F,F,F,F,F,F,F,F,F,F,F,F,  //a000 010010  GT    ~(NAN|Z|N)    より大きい
  8581:     T,F,T,F,T,T,T,T,F,F,F,F,T,T,T,T,  //af0f 010011  GE    Z|~(NAN|N)    より大きいか等しい
  8582:     F,F,F,F,F,F,F,F,T,F,T,F,F,F,F,F,  //00a0 010100  LT    N&~(NAN|Z)    より小さい
  8583:     F,F,F,F,T,T,T,T,T,F,T,F,T,T,T,T,  //0faf 010101  LE    Z|(N&~NAN)    より小さいか等しい
  8584:     T,F,T,F,F,F,F,F,T,F,T,F,F,F,F,F,  //a0a0 010110  GL    ~(NAN|Z)      等しくない
  8585:     T,F,T,F,T,F,T,F,T,F,T,F,T,F,T,F,  //aaaa 010111  GLE   ~NAN          より大きいか小さいか等しい
  8586:     F,T,F,T,F,T,F,T,F,T,F,T,F,T,F,T,  //5555 011000  NGLE  NAN           GLEでない
  8587:     F,T,F,T,T,T,T,T,F,T,F,T,T,T,T,T,  //5f5f 011001  NGL   NAN|Z         GLでない
  8588:     T,T,T,T,F,T,F,T,F,T,F,T,F,T,F,T,  //f555 011010  NLE   NAN|~(N|Z)    LEでない
  8589:     T,T,T,T,T,T,T,T,F,T,F,T,T,T,T,T,  //ff5f 011011  NLT   NAN|(Z|~N)    LTでない
  8590:     F,T,F,T,F,T,F,T,T,T,T,T,F,T,F,T,  //55f5 011100  NGE   NAN|(N&~Z)    GEでない
  8591:     F,T,F,T,T,T,T,T,T,T,T,T,T,T,T,T,  //5fff 011101  NGT   NAN|Z|N       GTでない
  8592:     T,T,T,T,F,F,F,F,T,T,T,T,F,F,F,F,  //f0f0 011110  SNE   ~Z            等しくない(シグナリング)
  8593:     T,T,T,T,T,T,T,T,T,T,T,T,T,T,T,T,  //ffff 011111  ST    1             真(シグナリング)
  8594:     //
  8595:     F,F,F,F,F,F,F,F,F,F,F,F,F,F,F,F,  //0000 100000
  8596:     F,F,F,F,T,T,T,T,F,F,F,F,T,T,T,T,  //0f0f 100001
  8597:     T,F,T,F,F,F,F,F,F,F,F,F,F,F,F,F,  //a000 100010
  8598:     T,F,T,F,T,T,T,T,F,F,F,F,T,T,T,T,  //af0f 100011
  8599:     F,F,F,F,F,F,F,F,T,F,T,F,F,F,F,F,  //00a0 100100
  8600:     F,F,F,F,T,T,T,T,T,F,T,F,T,T,T,T,  //0faf 100101
  8601:     T,F,T,F,F,F,F,F,T,F,T,F,F,F,F,F,  //a0a0 100110
  8602:     T,F,T,F,T,F,T,F,T,F,T,F,T,F,T,F,  //aaaa 100111
  8603:     F,T,F,T,F,T,F,T,F,T,F,T,F,T,F,T,  //5555 101000
  8604:     F,T,F,T,T,T,T,T,F,T,F,T,T,T,T,T,  //5f5f 101001
  8605:     T,T,T,T,F,T,F,T,F,T,F,T,F,T,F,T,  //f555 101010
  8606:     T,T,T,T,T,T,T,T,F,T,F,T,T,T,T,T,  //ff5f 101011
  8607:     F,T,F,T,F,T,F,T,T,T,T,T,F,T,F,T,  //55f5 101100
  8608:     F,T,F,T,T,T,T,T,T,T,T,T,T,T,T,T,  //5fff 101101
  8609:     T,T,T,T,F,F,F,F,T,T,T,T,F,F,F,F,  //f0f0 101110
  8610:     T,T,T,T,T,T,T,T,T,T,T,T,T,T,T,T,  //ffff 101111
  8611:     //
  8612:     F,F,F,F,F,F,F,F,F,F,F,F,F,F,F,F,  //0000 110000
  8613:     F,F,F,F,T,T,T,T,F,F,F,F,T,T,T,T,  //0f0f 110001
  8614:     T,F,T,F,F,F,F,F,F,F,F,F,F,F,F,F,  //a000 110010
  8615:     T,F,T,F,T,T,T,T,F,F,F,F,T,T,T,T,  //af0f 110011
  8616:     F,F,F,F,F,F,F,F,T,F,T,F,F,F,F,F,  //00a0 110100
  8617:     F,F,F,F,T,T,T,T,T,F,T,F,T,T,T,T,  //0faf 110101
  8618:     T,F,T,F,F,F,F,F,T,F,T,F,F,F,F,F,  //a0a0 110110
  8619:     T,F,T,F,T,F,T,F,T,F,T,F,T,F,T,F,  //aaaa 110111
  8620:     F,T,F,T,F,T,F,T,F,T,F,T,F,T,F,T,  //5555 111000
  8621:     F,T,F,T,T,T,T,T,F,T,F,T,T,T,T,T,  //5f5f 111001
  8622:     T,T,T,T,F,T,F,T,F,T,F,T,F,T,F,T,  //f555 111010
  8623:     T,T,T,T,T,T,T,T,F,T,F,T,T,T,T,T,  //ff5f 111011
  8624:     F,T,F,T,F,T,F,T,T,T,T,T,F,T,F,T,  //55f5 111100
  8625:     F,T,F,T,T,T,T,T,T,T,T,T,T,T,T,T,  //5fff 111101
  8626:     T,T,T,T,F,F,F,F,T,T,T,T,F,F,F,F,  //f0f0 111110
  8627:     T,T,T,T,T,T,T,T,T,T,T,T,T,T,T,T,  //ffff 111111
  8628:   };
  8629: 
  8630:   //fpuInit ()
  8631:   //  FPUを初期化する
  8632:   //  これはmpuInit()から呼ばれる
  8633:   public static void fpuInit () {
  8634:     for (int i = 0; i < 256; i++) {
  8635:       FPU_FPSR_EXC_TO_AEXC[i] = (((i << 8 & (FPU_FPSR_EXC_BSUN | FPU_FPSR_EXC_SNAN | FPU_FPSR_EXC_OPERR)) != 0 ? FPU_FPSR_AEXC_IOP : 0) |
  8636:                                  ((i << 8 & FPU_FPSR_EXC_OVFL) != 0 ? FPU_FPSR_AEXC_OVFL : 0) |
  8637:                                  ((i << 8 & (FPU_FPSR_EXC_UNFL | FPU_FPSR_EXC_INEX2)) == (FPU_FPSR_EXC_UNFL | FPU_FPSR_EXC_INEX2) ? FPU_FPSR_AEXC_UNFL : 0) |
  8638:                                  ((i << 8 & FPU_FPSR_EXC_DZ) != 0 ? FPU_FPSR_AEXC_DZ : 0) |
  8639:                                  ((i << 8 & (FPU_FPSR_EXC_OVFL | FPU_FPSR_EXC_INEX2 | FPU_FPSR_EXC_INEX1)) != 0 ? FPU_FPSR_AEXC_INEX : 0));
  8640:     }
  8641:     //マザーボードコプロセッサ
  8642:     fpuMotherboardCoprocessor = new ExpressionEvaluator ();
  8643:     //on-chip FPU
  8644:     fpuOnChipFPU = new ExpressionEvaluator ();
  8645:     //浮動小数点命令を実行するFPU/FPCP
  8646:     fpuBox = currentMPU < Model.MPU_MC68LC040 ? fpuMotherboardCoprocessor : fpuOnChipFPU;
  8647:     //浮動小数点レジスタ
  8648:     fpuFPn = fpuBox.epbFPn;
  8649:     //数値演算プロセッサボード
  8650:     fpuCoproboard1 = new EFPBox ();
  8651:     fpuCoproboard1.epbSetMC68881 ();
  8652:     fpuCoproboard2 = new EFPBox ();
  8653:     fpuCoproboard2.epbSetMC68881 ();
  8654:   }  //fpuInit()
  8655: 
  8656: 
  8657: 
  8658:   //========================================================================================
  8659:   //$$DBG デバッガ共通コンポーネント
  8660: 
  8661:   public static final boolean DBG_ORI_BYTE_ZERO_D0 = true;  //true=ORI.B #$00,D0(オペコード0x0000)を不当命令とみなす機能を有効にする。暴走をなるべく早く検出することで暴走の原因を特定しやすくする
  8662: 
  8663:   public static boolean dbgHexSelected;  //true=16進数が選択されている
  8664:   public static int dbgHexValue;  //選択されている16進数の値
  8665:   public static int dbgSupervisorMode;  //0=ユーザモード,0以外=スーパーバイザモード
  8666:   public static JPopupMenu dbgPopupMenu;  //ポップアップメニュー
  8667:   public static JMenu dbgPopupIBPMenu;  //命令ブレークポイントメニュー
  8668:   public static SpinnerNumberModel dbgPopupIBPCurrentModel;  //現在値のスピナーモデル
  8669:   public static int dbgPopupIBPCurrentValue;  //現在値
  8670:   public static SpinnerNumberModel dbgPopupIBPThresholdModel;  //閾値のスピナーモデル
  8671:   public static int dbgPopupIBPThresholdValue;  //閾値
  8672:   public static JMenuItem dbgPopupIBPClearMenuItem;  //解除
  8673:   public static JMenu dbgPopupHexMenu;  //16進数メニュー
  8674:   public static JMenuItem dbgPopupDisMenuItem;  //逆アセンブル
  8675:   public static JMenuItem dbgPopupMemMenuItem;  //メモリダンプ
  8676:   public static JMenuItem dbgPopupCopyMenuItem;  //コピー
  8677:   public static JMenuItem dbgPopupSelectAllMenuItem;  //すべて選択
  8678:   public static JTextArea dbgPopupTextArea;  //ポップアップメニューを表示したテキストエリア
  8679:   public static int dbgEventMask;  //イベントマスク。0でないときチェンジリスナーとキャレットリスナーを無効化
  8680:   public static boolean dbgStopOnError;  //true=エラーが発生したときコアを止める
  8681:   public static boolean dbgOriByteZeroD0;  //true=ORI.B #$00,D0を不当命令とみなす。普段はOFFにしておくこと
  8682:   public static boolean dbgStopAtStart;  //true=実行開始位置で停止する
  8683: 
  8684:   //共通
  8685:   //  sb.append(DBG_SPACES,0,length)でStringBuilderに連続する空白を追加するための配列
  8686:   public static final char[] DBG_SPACES = (
  8687:     //         11111111112222222222333333333344444444445555555555666666666677777777778
  8688:     //12345678901234567890123456789012345678901234567890123456789012345678901234567890
  8689:     "                                                                                ").toCharArray ();
  8690: 
  8691:   public static final int DBG_DRP_VISIBLE_MASK = 1;  //レジスタウインドウが表示されている
  8692:   public static final int DBG_DDP_VISIBLE_MASK = 2;  //逆アセンブルリストウインドウが表示されている
  8693:   public static final int DBG_DMP_VISIBLE_MASK = 4;  //メモリダンプウインドウが表示されている
  8694:   public static final int DBG_BLG_VISIBLE_MASK = 8;  //分岐ログが表示されている
  8695:   public static final int DBG_PFV_VISIBLE_MASK = 16;  //プログラムフロービジュアライザが表示されている
  8696:   public static final int DBG_RBP_VISIBLE_MASK = 32;  //ラスタブレークポイントウインドウが表示されている
  8697:   public static final int DBG_DBP_VISIBLE_MASK = 64;  //データブレークポイントウインドウが表示されている
  8698:   public static final int DBG_SMT_VISIBLE_MASK = 128;  //表示モードテストが表示されている
  8699:   public static final int DBG_ATW_VISIBLE_MASK = 256;  //アドレス変換ウインドウが表示されている
  8700:   public static final int DBG_PAA_VISIBLE_MASK = 512;  //物理アドレス空間ウインドウが表示されている
  8701:   public static final int DBG_RTL_VISIBLE_MASK = 1024;  //ルートポインタリストが表示されている
  8702:   public static final int DBG_SPV_VISIBLE_MASK = 2048;  //スプライトパターンビュアが表示されている
  8703:   public static final int DBG_ACM_VISIBLE_MASK = 4096;  //アドレス変換キャッシュモニタが表示されている
  8704:   public static int dbgVisibleMask;  //表示されているデバッグ関連ウインドウのマスク
  8705: 
  8706:   //dbgInit ()
  8707:   //  初期化
  8708:   public static void dbgInit () {
  8709:     dbgVisibleMask = 0;
  8710:     dbgHexSelected = false;
  8711:     dbgHexValue = 0;
  8712:     dbgSupervisorMode = 1;
  8713:     dbgPopupMenu = null;
  8714:     dbgPopupDisMenuItem = null;
  8715:     dbgPopupMemMenuItem = null;
  8716:     dbgPopupCopyMenuItem = null;
  8717:     dbgPopupSelectAllMenuItem = null;
  8718:     dbgPopupIBPMenu = null;
  8719:     dbgPopupIBPCurrentModel = null;
  8720:     dbgPopupIBPCurrentValue = 0;
  8721:     dbgPopupIBPThresholdModel = null;
  8722:     dbgPopupIBPThresholdValue = 0;
  8723:     dbgPopupHexMenu = null;
  8724:     dbgPopupTextArea = null;
  8725:     dbgEventMask = 0;
  8726:     dbgStopOnError = false;  //ウインドウを表示する前にも必要なのでここで初期化すること
  8727:     if (DBG_ORI_BYTE_ZERO_D0) {
  8728:       dbgOriByteZeroD0 = false;
  8729:     }
  8730:     dbgStopAtStart = false;
  8731:   }  //dbgInit()
  8732: 
  8733:   //dbgMakePopup ()
  8734:   //  デバッグ関連ウインドウの共通コンポーネントを作る
  8735:   public static void dbgMakePopup () {
  8736: 
  8737:     //ポップアップメニュー
  8738:     ActionListener popupActionListener = new ActionListener () {
  8739:       @Override public void actionPerformed (ActionEvent ae) {
  8740:         switch (ae.getActionCommand ()) {
  8741:         case "Disassemble":
  8742:           DisassembleList.ddpBacktraceRecord = -1L;  //分岐レコードの選択を解除する
  8743:           DisassembleList.ddpOpen (dbgHexValue, dbgSupervisorMode, false);
  8744:           break;
  8745:         case "Memory Dump":
  8746:           MemoryDumpList.dmpOpen (dbgHexValue, dbgSupervisorMode, false);
  8747:           break;
  8748:         case "Run to Here":
  8749:           if (InstructionBreakPoint.IBP_ON) {
  8750:             if (mpuTask == null) {
  8751:               InstructionBreakPoint.ibpInstant (DisassembleList.ddpPopupAddress, DisassembleList.ddpSupervisorMode);
  8752:               mpuStart ();
  8753:             }
  8754:           }
  8755:           break;
  8756:         case "Set Breakpoint":
  8757:           if (InstructionBreakPoint.IBP_ON) {
  8758:             InstructionBreakPoint.ibpPut (DisassembleList.ddpPopupAddress, DisassembleList.ddpSupervisorMode, dbgPopupIBPCurrentValue, dbgPopupIBPThresholdValue, null);
  8759:             DisassembleList.ddpOpen (0, DisassembleList.ddpSupervisorMode, true);
  8760:           }
  8761:           break;
  8762:         case "Clear Breakpoint":
  8763:           if (InstructionBreakPoint.IBP_ON) {
  8764:             InstructionBreakPoint.ibpRemove (DisassembleList.ddpPopupAddress, DisassembleList.ddpSupervisorMode);
  8765:             DisassembleList.ddpOpen (0, DisassembleList.ddpSupervisorMode, true);
  8766:           }
  8767:           break;
  8768:         case "Copy":
  8769:           dbgCopy ();
  8770:           break;
  8771:         case "Select All":
  8772:           dbgSelectAll ();
  8773:           break;
  8774:         }
  8775:       }
  8776:     };
  8777:     dbgPopupMenu = ComponentFactory.createPopupMenu (
  8778:       dbgPopupIBPMenu =
  8779:       InstructionBreakPoint.IBP_ON ?
  8780:       ComponentFactory.createMenu (
  8781:         "XXXXXXXX", KeyEvent.VK_UNDEFINED,
  8782:         Multilingual.mlnText (ComponentFactory.createMenuItem ("Run to Here", 'R', popupActionListener), "ja", "ここまで実行"),
  8783:         ComponentFactory.createHorizontalSeparator (),
  8784:         Multilingual.mlnText (ComponentFactory.createMenuItem ("Set Breakpoint", 'S', popupActionListener), "ja", "ブレークポイントを設定"),
  8785:         ComponentFactory.createHorizontalBox (
  8786:           Box.createHorizontalStrut (7),
  8787:           Box.createHorizontalGlue (),
  8788:           ComponentFactory.setPreferredSize (
  8789:             Multilingual.mlnText (ComponentFactory.createLabel ("current"), "ja", "現在値"),
  8790:             60, 16),
  8791:           ComponentFactory.createNumberSpinner (dbgPopupIBPCurrentModel = new SpinnerNumberModel (0, 0, 0x7fffffff, 1), 10, new ChangeListener () {
  8792:             @Override public void stateChanged (ChangeEvent ce) {
  8793:               dbgPopupIBPCurrentValue = dbgPopupIBPCurrentModel.getNumber ().intValue ();
  8794:             }
  8795:           }),
  8796:           Box.createHorizontalGlue ()
  8797:           ),
  8798:         ComponentFactory.createHorizontalBox (
  8799:           Box.createHorizontalStrut (7),
  8800:           Box.createHorizontalGlue (),
  8801:           ComponentFactory.setPreferredSize (
  8802:             Multilingual.mlnText (ComponentFactory.createLabel ("threshold"), "ja", "閾値"),
  8803:             60, 16),
  8804:           ComponentFactory.createNumberSpinner (dbgPopupIBPThresholdModel = new SpinnerNumberModel (0, 0, 0x7fffffff, 1), 10, new ChangeListener () {
  8805:             @Override public void stateChanged (ChangeEvent ce) {
  8806:               dbgPopupIBPThresholdValue = dbgPopupIBPThresholdModel.getNumber ().intValue ();
  8807:             }
  8808:           }),
  8809:           Box.createHorizontalGlue ()
  8810:           ),
  8811:         dbgPopupIBPClearMenuItem =
  8812:         Multilingual.mlnText (ComponentFactory.createMenuItem ("Clear Breakpoint", 'C', popupActionListener), "ja", "ブレークポイントを消去")
  8813:         ) :
  8814:       null,
  8815:       dbgPopupHexMenu =
  8816:       ComponentFactory.createMenu (
  8817:         "XXXXXXXX", KeyEvent.VK_UNDEFINED,
  8818:         dbgPopupDisMenuItem = Multilingual.mlnText (ComponentFactory.createMenuItem ("Disassemble", 'D', popupActionListener), "ja", "逆アセンブル"),
  8819:         dbgPopupMemMenuItem = Multilingual.mlnText (ComponentFactory.createMenuItem ("Memory Dump", 'M', popupActionListener), "ja", "メモリダンプ")
  8820:         ),
  8821:       dbgPopupCopyMenuItem = Multilingual.mlnText (ComponentFactory.createMenuItem ("Copy", 'C', popupActionListener), "ja", "コピー"),
  8822:       dbgPopupSelectAllMenuItem = Multilingual.mlnText (ComponentFactory.createMenuItem ("Select All", 'A', popupActionListener), "ja", "すべて選択")
  8823:       );
  8824: 
  8825:   }  //dbgMakePopup()
  8826: 
  8827:   //dbgShowPopup (me, textArea, dis)
  8828:   //  ポップアップメニューを表示する
  8829:   public static void dbgShowPopup (MouseEvent me, JTextArea textArea, boolean dis) {
  8830:     dbgEventMask++;
  8831:     int x = me.getX ();
  8832:     int y = me.getY ();
  8833:     //int p = textArea.viewToModel (me.getPoint ());  //クリックされた位置。viewToModel2Dは9から
  8834:     int p = textArea.viewToModel2D (me.getPoint ());  //クリックされた位置。viewToModel2Dは9から
  8835:     DisassembleList.ddpPopupAddress = -1;  //クリックされた行のアドレス
  8836:     if (dis) {
  8837:       int i = Arrays.binarySearch (DisassembleList.ddpSplitArray, 1, DisassembleList.ddpItemCount, p + 1);
  8838:       i = (i >> 31 ^ i) - 1;  //クリックされた項目の番号
  8839:       DisassembleList.ddpPopupAddress = DisassembleList.ddpAddressArray[i];  //クリックされた項目の先頭アドレス
  8840:     }
  8841:     int start = textArea.getSelectionStart ();  //選択範囲の開始位置
  8842:     int end = textArea.getSelectionEnd ();  //選択範囲の終了位置
  8843:     String text = textArea.getText ();  //テキスト全体
  8844:     int length = text.length ();  //テキスト全体の長さ
  8845:     if ((start == end ||  //選択範囲がないか
  8846:          p < start || end <= p) &&  //選択範囲の外側がクリックされて
  8847:         0 <= p && p < length && isWord (text.charAt (p))) {  //クリックされた位置に単語があるとき
  8848:       //クリックされた位置にある単語を選択する
  8849:       for (start = p; 0 < start && isWord (text.charAt (start - 1)); start--) {
  8850:       }
  8851:       for (end = p + 1; end < length && isWord (text.charAt (end)); end++) {
  8852:       }
  8853:       textArea.select (start, end);
  8854:     }
  8855:     dbgHexSelected = false;
  8856:     if (start < end) {  //選択範囲があるとき
  8857:       textArea.requestFocusInWindow ();  //フォーカスがないと選択範囲が見えない
  8858:       //選択範囲にある16進数の文字を取り出す
  8859:       //  以下の条件を加える
  8860:       //    選択範囲に16進数以外の単語の文字がないこと
  8861:       //    選択範囲に16進数の文字が9文字以上ないこと
  8862:       //    16進数の文字が偶数文字ずつの塊になっていること
  8863:       dbgHexValue = 0;
  8864:       int n = 0;
  8865:       for (int i = start; i < end; i++) {
  8866:         int t;
  8867:         if ((t = Character.digit (text.charAt (i), 16)) >= 0) {  //16進数の文字
  8868:           dbgHexValue = dbgHexValue << 4 | t;
  8869:           if (n >= 8 ||  //選択範囲に16進数の文字が9文字以上ある
  8870:               i + 1 >= end || (t = Character.digit (text.charAt (i + 1), 16)) < 0) {  //16進数の文字が偶数文字ずつの塊になっていない
  8871:             n = 0;
  8872:             break;
  8873:           }
  8874:           dbgHexValue = dbgHexValue << 4 | t;
  8875:           n += 2;
  8876:           i++;
  8877:         } else if (isWord (text.charAt (i))) {  //16進数以外の単語の文字
  8878:           n = 0;
  8879:           break;
  8880:         }
  8881:       }
  8882:       dbgHexSelected = n > 0;
  8883:       try {
  8884:         //Rectangle r = textArea.modelToView (start).getBounds ();  //modelToView2Dは9から
  8885:         Rectangle r = textArea.modelToView2D (start).getBounds ();  //modelToView2Dは9から
  8886:         //Rectangle s = textArea.modelToView (end - 1).getBounds ();  //modelToView2Dは9から
  8887:         Rectangle s = textArea.modelToView2D (end - 1).getBounds ();  //modelToView2Dは9から
  8888:         if (r.y == s.y) {  //選択範囲が1行だけのとき
  8889:           //選択範囲を隠してしまわないようにポップアップを選択範囲の下側に表示する
  8890:           y = r.y + r.height;
  8891:         }
  8892:       } catch (BadLocationException ble) {
  8893:       }
  8894:     }
  8895:     //逆アセンブルリストでコアが止まっていて選択範囲がなくてクリックされた行のアドレスがわかるとき命令ブレークポイントメニューが有効
  8896:     if (InstructionBreakPoint.IBP_ON) {
  8897:       if (dis && mpuTask == null && DisassembleList.ddpPopupAddress != -1) {
  8898:         ComponentFactory.setText (dbgPopupIBPMenu, fmtHex8 (DisassembleList.ddpPopupAddress));
  8899:         TreeMap<Integer,InstructionBreakPoint.InstructionBreakRecord> pointTable = DisassembleList.ddpSupervisorMode != 0 ? InstructionBreakPoint.ibpSuperPointTable : InstructionBreakPoint.ibpUserPointTable;
  8900:         InstructionBreakPoint.InstructionBreakRecord r = pointTable.get (DisassembleList.ddpPopupAddress);
  8901:         if (r != null) {  //命令ブレークポイントがあるとき
  8902:           dbgPopupIBPCurrentModel.setValue (Integer.valueOf (dbgPopupIBPCurrentValue = r.ibrValue));  //現在値
  8903:           dbgPopupIBPThresholdModel.setValue (Integer.valueOf (dbgPopupIBPThresholdValue = r.ibrThreshold));  //閾値
  8904:           dbgPopupIBPClearMenuItem.setEnabled (true);  //消去できる
  8905:         } else {  //命令ブレークポイントがないとき
  8906:           dbgPopupIBPCurrentModel.setValue (Integer.valueOf (dbgPopupIBPCurrentValue = 0));  //現在値
  8907:           dbgPopupIBPThresholdModel.setValue (Integer.valueOf (dbgPopupIBPThresholdValue = 0));  //閾値
  8908:           dbgPopupIBPClearMenuItem.setEnabled (false);  //消去できない
  8909:         }
  8910:         ComponentFactory.setVisible (dbgPopupIBPMenu, true);
  8911:       } else {
  8912:         ComponentFactory.setVisible (dbgPopupIBPMenu, false);
  8913:       }
  8914:     }
  8915:     //16進数が選択されていれば16進数メニューが有効
  8916:     if (dbgHexSelected) {
  8917:       ComponentFactory.setText (dbgPopupHexMenu, fmtHex8 (dbgHexValue));
  8918:       ComponentFactory.setVisible (dbgPopupHexMenu, true);
  8919:     } else {
  8920:       ComponentFactory.setVisible (dbgPopupHexMenu, false);
  8921:     }
  8922:     //選択範囲があればコピーが有効
  8923:     ComponentFactory.setEnabled (dbgPopupCopyMenuItem, clpClipboard != null && start < end);
  8924:     //クリップボードがあればすべて選択が有効
  8925:     ComponentFactory.setEnabled (dbgPopupSelectAllMenuItem, clpClipboard != null);
  8926:     //ポップアップメニューを表示する
  8927:     dbgPopupTextArea = textArea;
  8928:     dbgPopupMenu.show (textArea, x, y);
  8929:     dbgEventMask--;
  8930:   }  //dbgShowPopup(MouseEvent,JTextArea,boolean)
  8931: 
  8932:   public static boolean isWord (char c) {
  8933:     return '0' <= c && c <= '9' || 'A' <= c && c <= 'Z' || 'a' <= c && c <= 'z' || c == '_';
  8934:   }  //isWord(char)
  8935: 
  8936:   //dbgCopy ()
  8937:   //  コピー
  8938:   public static void dbgCopy () {
  8939:     if (clpClipboard != null) {
  8940:       //選択範囲の文字列をコピーする
  8941:       String selectedText = dbgPopupTextArea.getSelectedText ();
  8942:       if (selectedText != null) {
  8943:         clpClipboardString = selectedText;
  8944:         try {
  8945:           clpClipboard.setContents (clpStringContents, clpClipboardOwner);
  8946:           clpIsClipboardOwner = true;  //自分がコピーした
  8947:         } catch (Exception e) {
  8948:           return;
  8949:         }
  8950:       }
  8951:     }
  8952:   }  //dbgCopy()
  8953: 
  8954:   //dbgSelectAll ()
  8955:   //  すべて選択
  8956:   public static void dbgSelectAll () {
  8957:     if (clpClipboard != null) {
  8958:       //すべて選択する
  8959:       dbgEventMask++;
  8960:       dbgPopupTextArea.selectAll ();
  8961:       dbgPopupTextArea.requestFocusInWindow ();
  8962:       dbgEventMask--;
  8963:     }
  8964:   }  //dbgSelectAll()
  8965: 
  8966:   //dbgUpdate ()
  8967:   //  デバッグウインドウを更新する
  8968:   //  コアのrun()の末尾でdbgVisibleMask!=0のとき呼び出す
  8969:   public static void dbgUpdate () {
  8970:     if ((dbgVisibleMask & DBG_DRP_VISIBLE_MASK) != 0) {
  8971:       RegisterList.drpUpdate ();  //レジスタウインドウを更新する
  8972:     }
  8973:     if (ProgramFlowVisualizer.PFV_ON) {
  8974:       if ((dbgVisibleMask & DBG_PFV_VISIBLE_MASK) != 0) {
  8975:         if (ProgramFlowVisualizer.pfvTimer == 0) {
  8976:           ProgramFlowVisualizer.pfvUpdate ();  //プログラムフロービジュアライザを更新する
  8977:         } else {
  8978:           ProgramFlowVisualizer.pfvTimer--;
  8979:         }
  8980:       }
  8981:     }
  8982:     if (RasterBreakPoint.RBP_ON) {
  8983:       if ((dbgVisibleMask & DBG_RBP_VISIBLE_MASK) != 0) {
  8984:         if (RasterBreakPoint.rbpTimer == 0) {
  8985:           RasterBreakPoint.rbpUpdateFrame ();  //ラスタブレークポイントウインドウを更新する
  8986:         } else {
  8987:           RasterBreakPoint.rbpTimer--;
  8988:         }
  8989:       }
  8990:     }
  8991:     if (ScreenModeTest.SMT_ON) {
  8992:       if ((dbgVisibleMask & DBG_SMT_VISIBLE_MASK) != 0) {
  8993:         if (ScreenModeTest.smtTimer == 0) {
  8994:           ScreenModeTest.smtUpdateFrame ();  //表示モードテストウインドウを更新する
  8995:         } else {
  8996:           ScreenModeTest.smtTimer--;
  8997:         }
  8998:       }
  8999:     }
  9000:     if (RootPointerList.RTL_ON) {
  9001:       if ((dbgVisibleMask & DBG_RTL_VISIBLE_MASK) != 0) {
  9002:         if (RootPointerList.rtlTimer == 0) {
  9003:           RootPointerList.rtlTimer = RootPointerList.RTL_INTERVAL - 1;
  9004:           RootPointerList.rtlUpdateFrame ();  //ルートポインタリストを更新する
  9005:         } else {
  9006:           RootPointerList.rtlTimer--;
  9007:         }
  9008:       }
  9009:     }
  9010:     if (SpritePatternViewer.SPV_ON) {
  9011:       if ((dbgVisibleMask & DBG_SPV_VISIBLE_MASK) != 0) {
  9012:         if (SpritePatternViewer.spvTimer == 0) {
  9013:           SpritePatternViewer.spvTimer = SpritePatternViewer.SPV_INTERVAL - 1;
  9014:           SpritePatternViewer.spvUpdateFrame ();  //スプライトパターンビュアを更新する
  9015:         } else {
  9016:           SpritePatternViewer.spvTimer--;
  9017:         }
  9018:       }
  9019:     }
  9020:     if (ATCMonitor.ACM_ON) {
  9021:       if ((dbgVisibleMask & DBG_ACM_VISIBLE_MASK) != 0) {
  9022:         if (ATCMonitor.acmTimer == 0) {
  9023:           ATCMonitor.acmTimer = ATCMonitor.ACM_INTERVAL - 1;
  9024:           ATCMonitor.acmUpdateFrame ();  //アドレス変換キャッシュモニタを更新する
  9025:         } else {
  9026:           ATCMonitor.acmTimer--;
  9027:         }
  9028:       }
  9029:     }
  9030:   }  //dbgUpdate()
  9031: 
  9032:   //dbgDoStopOnError ()
  9033:   //  エラーで停止する
  9034:   //  エラーを検出して例外スタックフレームを構築した後にdbgStopOnErrorならば呼び出してコアを停止させる
  9035:   //
  9036:   //  Human68kの_BUS_ERRの中では停止させない
  9037:   //  human302のシステムディスクで起動した場合、
  9038:   //  SCSIボード、RS-232Cボード、MIDIボードのテストで_BUS_ERRが呼び出されてバスエラーが発生する
  9039:   //    bus error on reading from 00EA0044 at 0000E2F4
  9040:   //    bus error on reading from 00EAFC04 at 0002D04A
  9041:   //    bus error on reading from 00EAFC14 at 0002D04A
  9042:   //    bus error on reading from 00EAFA01 at 0005CD54
  9043:   //  _BUS_ERRはレベル0で入ったDOSコールの番号を更新しないので、_BUS_ERRの中かどうかはpcで判断する
  9044:   //    0x0000e342 <= pc0 && pc0 < 0x0000e3b6  human200/human201の_BUS_ERR
  9045:   //    0x0000e3c8 <= pc0 && pc0 < 0x0000e43c  human202の_BUS_ERR
  9046:   //    0x0000e1a8 <= pc0 && pc0 < 0x0000e21c  human203の_BUS_ERR
  9047:   //    0x0000e256 <= pc0 && pc0 < 0x0000e2ca  human215の_BUS_ERR
  9048:   //    0x0000e174 <= pc0 && pc0 < 0x0000e1e8  human301の_BUS_ERR
  9049:   //    0x0000e28a <= pc0 && pc0 < 0x0000e2fe  human302の_BUS_ERR
  9050:   public static boolean dbgDoStopOnError () {
  9051:     String message = (
  9052:       M68kException.m6eNumber < 0 ?
  9053:       fmtHex8 (new StringBuilder ("breaked").append (" at "), regPC0).toString () :
  9054:       M68kException.m6eNumber <= M68kException.M6E_ADDRESS_ERROR ?
  9055:       fmtHex8 (fmtHex8 (new StringBuilder ("ERROR: ").append (M68kException.M6E_ERROR_NAME[M68kException.m6eNumber])
  9056:                         .append (M68kException.m6eDirection == 0 ? " on writing to " : " on reading from "), M68kException.m6eAddress)
  9057:                .append (" at "), regPC0).toString () :
  9058:       fmtHex8 (new StringBuilder (M68kException.M6E_ERROR_NAME[M68kException.m6eNumber])
  9059:                .append (" at "), regPC0).toString ()
  9060:       );
  9061:     System.out.println (message);
  9062:     if (!(M68kException.m6eNumber == M68kException.M6E_ACCESS_FAULT &&
  9063:           0x0000e100 <= regPC0 && regPC0 < 0x0000e500)) {  //_BUS_ERRの中で発生したバスエラーでないとき
  9064:       mpuStop (message);
  9065:       return true;
  9066:     }
  9067:     return false;
  9068:   }  //dbgDoStopOnError()
  9069: 
  9070:   //dbgDoubleBusFault ()
  9071:   //  ダブルバスフォルト
  9072:   public static void dbgDoubleBusFault () {
  9073:     String message =
  9074:       fmtHex8 (fmtHex8 (new StringBuilder ("FATAL ERROR: ").append (M68kException.M6E_ERROR_NAME[M68kException.m6eNumber])
  9075:                         .append (M68kException.m6eDirection == 0 ? " on writing to " : " on reading from "), M68kException.m6eAddress)
  9076:                .append (" at "), regPC0).toString ();
  9077:     System.out.println (message);
  9078:     mpuStop (message);
  9079:   }  //dbgDoubleBusFault()
  9080: 
  9081: 
  9082: 
  9083:   //========================================================================================
  9084:   //$$RSC ResourceFile
  9085: 
  9086:   public static final HashMap<String,byte[]> rscResourceCache = new HashMap<String,byte[]> ();
  9087: 
  9088:   //array = rscGetResource (name, sizes...)
  9089:   //  リソースファイルを読み込む。null=読み込めなかった
  9090:   //  ファイル名をコンマで区切る機能はない。XEiJ.jarの中なので必要ない
  9091:   //  *.zipや*.gzは非対応。XEiJ.jarの中なので必要ない
  9092:   //  キャッシュした配列をそのまま返すので書き換えないように注意すること
  9093:   public static byte[] rscGetResource (String name, int... sizes) {
  9094:     byte[] array = rscResourceCache.get (name);  //キャッシュから出す
  9095:     if (array != null) {  //読み込み済み
  9096:       return array;
  9097:     }
  9098:     array = new byte[1024 * 64];  //最初は64KB
  9099:     int size = 0;  //これまでに読み込んだ長さ
  9100:     try (BufferedInputStream bis = new BufferedInputStream (XEiJ.class.getResourceAsStream ("../data/" + name))) {
  9101:       for (;;) {
  9102:         if (size == array.length) {  //配列が一杯
  9103:           byte[] newArray = new byte[array.length * 2];  //2倍に伸ばした配列を作る
  9104:           System.arraycopy (array, 0, newArray, 0, size);  //読み込んだ部分を新しい配列に移す
  9105:           array = newArray;  //新しい配列に移行する
  9106:         }
  9107:         int step = bis.read (array, size, array.length - size);  //続きを読み込む。今回読み込んだ長さ
  9108:         if (step == -1) {  //終わり
  9109:           break;
  9110:         }
  9111:         size += step;  //これまでに読み込んだ長さ
  9112:       }
  9113:       if (size < array.length) {  //配列が長すぎる
  9114:         byte[] newArray = new byte[size];  //切り詰めた配列を作る
  9115:         System.arraycopy (array, 0, newArray, 0, size);  //読み込んだ部分を新しい配列に移す
  9116:         array = newArray;  //新しい配列に移行する
  9117:       }
  9118:       boolean fit = sizes.length == 0;
  9119:       if (!fit) {
  9120:         for (int i = 0; i < sizes.length; i++) {
  9121:           if (size == sizes[i]) {  //サイズが合っている
  9122:             fit = true;
  9123:             break;
  9124:           }
  9125:         }
  9126:       }
  9127:       if (fit) {
  9128:         System.out.println (Multilingual.mlnJapanese ?
  9129:                             name + " を読み込みました" :
  9130:                             name + " was read");
  9131:         rscResourceCache.put (name, array);  //キャッシュに入れる
  9132:         return array;  //try-with-resourcesなのでここでクローズされる
  9133:       }
  9134:       System.out.println (Multilingual.mlnJapanese ?
  9135:                           name + " のサイズが違います" :
  9136:                           name + " has wrong size");
  9137:       return null;  //try-with-resourcesなのでここでクローズされる
  9138:     } catch (IOException ioe) {
  9139:     }
  9140:     //try-with-resourcesなのでここでクローズされる
  9141:     System.out.println (Multilingual.mlnJapanese ?
  9142:                         name + " を読み込めません" :
  9143:                         name + " cannot be read");
  9144:     return null;
  9145:   }
  9146: 
  9147:   //string = rscGetResourceText (name, charset)
  9148:   //  リソースファイルからテキストを読み込む
  9149:   public static String rscGetResourceText (String name) {
  9150:     return rscGetResourceText (name, "UTF-8");
  9151:   }
  9152:   public static String rscGetResourceText (String name, String charset) {
  9153:     byte[] array = rscGetResource (name);
  9154:     if (name != null) {
  9155:       try {
  9156:         return new String (array, charset);
  9157:       } catch (UnsupportedEncodingException uee) {
  9158:       }
  9159:     }
  9160:     return "";
  9161:   }
  9162: 
  9163:   public static final Pattern RSC_ZIP_SEPARATOR = Pattern.compile ("(?<=\\.(?:jar|zip))(?:/|\\\\)(?=.)", Pattern.CASE_INSENSITIVE);
  9164:   public static String rscLastFileName = null;  //最後に読み込んだファイル名
  9165: 
  9166:   //array = rscGetFile (names, sizes...)
  9167:   //  ファイルを読み込む。null=読み込めなかった
  9168:   //  コンマで区切られたファイルを順に探して最初に読み込めたものを返す
  9169:   //  *.zip/entryを指定するとエントリを読み込む
  9170:   //  *.gzを指定すると解凍する
  9171:   public static byte[] rscGetFile (String names, int... sizes) {
  9172:     for (String name : names.split (",")) {  //コンマで区切る
  9173:       name = name.trim ();  //前後の空白を削除する
  9174:       if (name.length () == 0 || name.equalsIgnoreCase ("none")) {
  9175:         continue;
  9176:       }
  9177:       String[] zipSplittedName = RSC_ZIP_SEPARATOR.split (name, 2);  // *.zip/entryを*.zipとentryに分ける
  9178:       InputStream is = null;
  9179:       if (zipSplittedName.length < 2) {  // *.zip/entryではない
  9180:         File file = new File (name);
  9181:         if (file.isFile ()) {  //ファイルがある
  9182:           try {
  9183:             is = new FileInputStream (file);  //ファイルを開く
  9184:           } catch (IOException ioe) {
  9185:           }
  9186:         } else {  //ファイルがない
  9187:           System.out.println (Multilingual.mlnJapanese ?
  9188:                               name + " がありません" :
  9189:                               name + " does not exist");
  9190:           continue;
  9191:         }
  9192:       } else {  // *.zip/entry
  9193:         String zipName = zipSplittedName[0];  // *.zip
  9194:         String entryName = zipSplittedName[1];  //entry
  9195:         if (new File (zipName).isFile ()) {  //ファイルがある
  9196:           try {
  9197:             ZipFile zipFile = new ZipFile (zipName);  //ファイル
  9198:             ZipEntry zipEntry = zipFile.getEntry (entryName);  //エントリ
  9199:             if (zipEntry != null) {  //エントリがある
  9200:               is = zipFile.getInputStream (zipEntry);  //エントリを開く
  9201:             } else {  //エントリがない
  9202:               System.out.println (Multilingual.mlnJapanese ?
  9203:                                   zipName + " に " + zipEntry + " がありません" :
  9204:                                   zipName + " does not include " + zipEntry);
  9205:             }
  9206:           } catch (IOException ioe) {
  9207:           }
  9208:         } else {  //ファイルがない
  9209:           System.out.println (Multilingual.mlnJapanese ?
  9210:                               zipName + " がありません" :
  9211:                               zipName + " does not exist");
  9212:           continue;
  9213:         }
  9214:       }
  9215:       if (is != null) {  //開けた
  9216:         try {
  9217:           is = new BufferedInputStream (is);
  9218:           if (name.toLowerCase ().endsWith (".gz")) {  // *.gz
  9219:             is = new GZIPInputStream (is);  //展開する
  9220:           }
  9221:           byte[] array = new byte[1024 * 64];  //最初は64KB
  9222:           int size = 0;  //これまでに読み込んだ長さ
  9223:           for (;;) {
  9224:             if (size == array.length) {  //配列が一杯
  9225:               byte[] newArray = new byte[array.length * 2];  //2倍に伸ばした配列を作る
  9226:               System.arraycopy (array, 0, newArray, 0, size);  //読み込んだ部分を新しい配列に移す
  9227:               array = newArray;  //新しい配列に移行する
  9228:             }
  9229:             int step = is.read (array, size, array.length - size);  //続きを読み込む。今回読み込んだ長さ
  9230:             if (step == -1) {  //終わり
  9231:               break;
  9232:             }
  9233:             size += step;  //これまでに読み込んだ長さ
  9234:           }
  9235:           is.close ();  //ここはtry-with-resourcesではないので明示的にクローズすること
  9236:           is = null;
  9237:           if (size < array.length) {  //配列が長すぎる
  9238:             byte[] newArray = new byte[size];  //切り詰めた配列を作る
  9239:             System.arraycopy (array, 0, newArray, 0, size);  //読み込んだ部分を新しい配列に移す
  9240:             array = newArray;  //新しい配列に移行する
  9241:           }
  9242:           boolean fit = sizes.length == 0;
  9243:           if (!fit) {
  9244:             for (int i = 0; i < sizes.length; i++) {
  9245:               if (size == sizes[i]) {  //サイズが合っている
  9246:                 fit = true;
  9247:                 break;
  9248:               }
  9249:             }
  9250:           }
  9251:           if (fit) {
  9252:             System.out.println (Multilingual.mlnJapanese ?
  9253:                                 name + " を読み込みました" :
  9254:                                 name + " was read");
  9255:             rscLastFileName = name;  //最後に読み込んだファイル名
  9256:             return array;  //配列を返す
  9257:           }
  9258:           System.out.println (Multilingual.mlnJapanese ?
  9259:                               name + " のサイズが違います" :
  9260:                               name + " has wrong size");
  9261:           continue;
  9262:         } catch (IOException ioe) {
  9263:         }
  9264:         if (is != null) {
  9265:           try {
  9266:             is.close ();  //ここはtry-with-resourcesではないので明示的にクローズすること
  9267:             is = null;
  9268:           } catch (IOException ioe) {
  9269:           }
  9270:         }
  9271:       }  //if 開けた
  9272:       System.out.println (Multilingual.mlnJapanese ?
  9273:                           name + " を読み込めません" :
  9274:                           name + " cannot be read");
  9275:     }  //for name
  9276:     //読み込めなかった
  9277:     //ファイル名が指定されたときはメッセージが表示される
  9278:     //ファイル名が指定されなかったときはエラーメッセージも表示されない
  9279:     return null;
  9280:   }
  9281: 
  9282:   //string = rscGetTextFile (name)
  9283:   //string = rscGetTextFile (name, charset)
  9284:   //  テキストファイルを読み込む
  9285:   public static String rscGetTextFile (String name) {
  9286:     return rscGetTextFile (name, "UTF-8");
  9287:   }
  9288:   public static String rscGetTextFile (String name, String charset) {
  9289:     byte[] array = rscGetFile (name);
  9290:     if (array != null) {
  9291:       try {
  9292:         return new String (array, charset);
  9293:       } catch (UnsupportedEncodingException uee) {
  9294:       }
  9295:     }
  9296:     return "";
  9297:   }
  9298: 
  9299:   //mask = rscShowError (message, mask)
  9300:   //  ファイル操作に失敗したときに表示するダイアログ
  9301:   public static final int RSC_A_MASK = 1;  //中止
  9302:   public static final int RSC_R_MASK = 2;  //再実行
  9303:   public static final int RSC_I_MASK = 4;  //無視
  9304:   public static final String RSC_A_EN = "Abort";
  9305:   public static final String RSC_R_EN = "Retry";
  9306:   public static final String RSC_I_EN = "Ignore";
  9307:   public static final String RSC_A_JA = "中止";
  9308:   public static final String RSC_R_JA = "再実行";
  9309:   public static final String RSC_I_JA = "無視";
  9310:   public static final String[][] RSC_EN_OPTIONS = {
  9311:     { RSC_A_EN                     },
  9312:     { RSC_A_EN                     },
  9313:     {           RSC_R_EN           },
  9314:     { RSC_A_EN, RSC_R_EN           },
  9315:     {                     RSC_I_EN },
  9316:     { RSC_A_EN,           RSC_I_EN },
  9317:     {           RSC_R_EN, RSC_I_EN },
  9318:     { RSC_A_EN, RSC_R_EN, RSC_I_EN },
  9319:   };
  9320:   public static final String[][] RSC_JA_OPTIONS = {
  9321:     { RSC_A_JA                     },
  9322:     { RSC_A_JA                     },
  9323:     {           RSC_R_JA           },
  9324:     { RSC_A_JA, RSC_R_JA           },
  9325:     {                     RSC_I_JA },
  9326:     { RSC_A_JA,           RSC_I_JA },
  9327:     {           RSC_R_JA, RSC_I_JA },
  9328:     { RSC_A_JA, RSC_R_JA, RSC_I_JA },
  9329:   };
  9330:   public static int rscShowError (String message, int mask) {
  9331:     System.out.println (message);
  9332:     mask &= RSC_A_MASK | RSC_R_MASK | RSC_I_MASK;
  9333:     if (mask == 0) {
  9334:       mask = RSC_A_MASK;
  9335:     }
  9336:     String[] options = (Multilingual.mlnJapanese ? RSC_JA_OPTIONS : RSC_EN_OPTIONS)[mask];
  9337:     int def = Integer.numberOfTrailingZeros (mask);  //デフォルトの選択肢。0,1,2。中止、再実行、無視の順で最初に見つかったもの
  9338:     pnlExitFullScreen (true);
  9339:     int bit = JOptionPane.showOptionDialog (
  9340:       null,  //parentComponent
  9341:       message,  //message
  9342:       Multilingual.mlnJapanese ? "ファイル操作エラー" : "File operation error",  //title
  9343:       JOptionPane.YES_NO_CANCEL_OPTION,  //optionType
  9344:       JOptionPane.ERROR_MESSAGE,  //messageType
  9345:       null,  //icon
  9346:       options,  //options
  9347:       options[def]);  //initialValue
  9348:     if (bit == JOptionPane.CLOSED_OPTION) {  //閉じた。-1
  9349:       bit = def;
  9350:     }
  9351:     return 1 << bit;
  9352:   }
  9353: 
  9354:   //success = rscPutTextFile (name, string)
  9355:   //success = rscPutTextFile (name, strings)
  9356:   //success = rscPutTextFile (name, string, charset)
  9357:   //success = rscPutTextFile (name, strings, charset)
  9358:   //  テキストファイルに書き出す
  9359:   public static boolean rscPutTextFile (String name, String string) {
  9360:     return rscPutTextFile (name, string, "UTF-8");
  9361:   }
  9362:   public static boolean rscPutTextFile (String name, ArrayList<String> strings) {
  9363:     return rscPutTextFile (name, strings, "UTF-8");
  9364:   }
  9365:   public static boolean rscPutTextFile (String name, String string, String charset) {
  9366:     ArrayList<String> strings = new ArrayList<String> ();
  9367:     strings.add (string);
  9368:     return rscPutTextFile (name, strings, charset);
  9369:   }
  9370:   public static boolean rscPutTextFile (String name, ArrayList<String> strings, String charset) {
  9371:     String nameTmp = name + ".tmp";
  9372:     String nameBak = name + ".bak";
  9373:     File file = new File (name);
  9374:     File fileTmp = new File (nameTmp);
  9375:     File fileBak = new File (nameBak);
  9376:     //親ディレクトリがなければ作る
  9377:     File parentDirectory = file.getParentFile ();  //親ディレクトリ
  9378:     if (parentDirectory != null && !parentDirectory.isDirectory ()) {  //親ディレクトリがない
  9379:       if (!parentDirectory.mkdirs ()) {  //親ディレクトリを作る。必要ならば遡って作る。作れなかった
  9380:         System.out.println (parentDirectory.getPath () + (Multilingual.mlnJapanese ? " を作れません" : " cannot be created"));
  9381:         return false;
  9382:       }
  9383:     }
  9384:     //name.tmpがあればname.tmpを削除する
  9385:     if (fileTmp.exists ()) {  //name.tmpがある
  9386:       if (!fileTmp.delete ()) {  //name.tmpを削除する。削除できなかった
  9387:         System.out.println (nameTmp + (Multilingual.mlnJapanese ? " を削除できません" : " cannot be deleted"));
  9388:         return false;
  9389:       }
  9390:     }
  9391:     //name.tmpに出力する
  9392:     try (BufferedWriter bw = new BufferedWriter (new FileWriter (nameTmp, Charset.forName (charset)))) {
  9393:       for (String string : strings) {
  9394:         bw.write (string);
  9395:       }
  9396:     } catch (IOException ioe) {
  9397:       ioe.printStackTrace ();
  9398:       System.out.println (nameTmp + (Multilingual.mlnJapanese ? " に書き出せません" : " cannot be written"));
  9399:       return false;
  9400:     }
  9401:     //nameがあればnameをname.bakにリネームする
  9402:     boolean fileExists = file.exists ();
  9403:     if (fileExists) {  //nameがある
  9404:       //name.bakがあればname.bakを削除する
  9405:       if (fileBak.exists ()) {  //name.bakがある
  9406:         if (!fileBak.delete ()) {  //name.bakを削除する。削除できなかった
  9407:           System.out.println (nameBak + (Multilingual.mlnJapanese ? " を削除できません" : " cannot be deleted"));
  9408:           return false;
  9409:         }
  9410:       }
  9411:       //nameをname.bakにリネームする
  9412:       if (!file.renameTo (fileBak)) {  //nameをname.bakにリネームする。リネームできなかった
  9413:         System.out.println (name + (Multilingual.mlnJapanese ? " を " : " cannot be renamed to ") + nameBak + (Multilingual.mlnJapanese ? " にリネームできません" : ""));
  9414:         return false;
  9415:       }
  9416:     }
  9417:     //name.tmpをnameにリネームする
  9418:     if (!fileTmp.renameTo (file)) {  //name.tmpをnameにリネームする。リネームできなかった
  9419:       System.out.println (nameTmp + (Multilingual.mlnJapanese ? " を " : " cannot be renamed to ") + name + (Multilingual.mlnJapanese ? " にリネームできません" : ""));
  9420:       return false;
  9421:     }
  9422:     if (fileExists) {  //nameがあった
  9423:       System.out.println (name + (Multilingual.mlnJapanese ? " を更新しました" : " was updated"));
  9424:     } else {  //nameがあった
  9425:       System.out.println (name + (Multilingual.mlnJapanese ? " を作りました" : " was created"));
  9426:     }
  9427:     return true;
  9428:   }
  9429: 
  9430:   //success = rscPutFile (name, array)
  9431:   //success = rscPutFile (name, array, offset, length)
  9432:   //success = rscPutFile (name, array, offset, length, longLength2)
  9433:   //  ファイルに書き出す
  9434:   //  nameにarray[offset..offset+length-1]とlongLength2-length個の0を書き出す
  9435:   //  親ディレクトリがなければ作る
  9436:   //  同じ内容のファイルが既にあるときは更新しない
  9437:   //  *.zip/entryは非対応
  9438:   public static boolean rscPutFile (String name, byte[] array) {
  9439:     return rscPutFile (name, array, 0, array.length, (long) array.length);
  9440:   }
  9441:   public static boolean rscPutFile (String name, byte[] array, int offset, int length) {
  9442:     return rscPutFile (name, array, offset, length, (long) length);
  9443:   }
  9444:   public static boolean rscPutFile (String name, byte[] array, int offset, int length, long longLength2) {
  9445:     if (RSC_ZIP_SEPARATOR.matcher (name).matches ()) {  // *.zip/entry
  9446:       // *.zip/entryのとき確実に弾かないとファイルを破壊するおそれがある
  9447:       return false;
  9448:     }
  9449:     File file = new File (name);
  9450:     boolean fileExists = file.isFile ();  //true=同じ名前のファイルがある
  9451:     if (fileExists && file.length () == longLength2) {  //同じ名前で同じ長さのファイルがある
  9452:     comparison:
  9453:       {
  9454:         try (BufferedInputStream bis = new BufferedInputStream (new FileInputStream (file))) {
  9455:           byte[] buffer = new byte[(int) Math.min (Math.max ((long) length, longLength2 - (long) length), (long) (1024 * 1024))];  //最大1MBずつ読み込んで比較する
  9456:           int position = 0;
  9457:           while (position < length) {
  9458:             int step = bis.read (buffer, 0, Math.min (buffer.length, length - position));
  9459:             if (step == -1) {  //足りない。長さを確認してから始めたのだから途中で終わるはずがない
  9460:               break comparison;
  9461:             }
  9462:             int offsetPosition = offset + position;
  9463:             for (int i = 0; i < step; i++) {
  9464:               if (buffer[i] != array[offsetPosition + i]) {  //一致しない
  9465:                 break comparison;
  9466:               }
  9467:             }
  9468:             position += step;
  9469:           }
  9470:           long longPosition2 = (long) length;
  9471:           while (longPosition2 < longLength2) {
  9472:             int step = bis.read (buffer, 0, (int) Math.min ((long) buffer.length, longLength2 - longPosition2));
  9473:             if (step == -1) {  //足りない。長さを確認してから始めたのだから途中で終わるはずがない
  9474:               break comparison;
  9475:             }
  9476:             for (int i = 0; i < step; i++) {
  9477:               if (buffer[i] != 0) {  //一致しない
  9478:                 break comparison;
  9479:               }
  9480:             }
  9481:             longPosition2 += (long) step;
  9482:           }
  9483:           return true;  //一致した
  9484:         } catch (IOException ioe) {
  9485:         }
  9486:       }  //match
  9487:     }  //if 同じ名前で同じ長さのファイルがある
  9488:     String nameTmp = name + ".tmp";
  9489:     File fileTmp = new File (nameTmp);
  9490:     String nameBak = name + ".bak";
  9491:     File fileBak = new File (nameBak);
  9492:   retry:
  9493:     for (;;) {
  9494:       File parentDirectory = file.getParentFile ();  //親ディレクトリ
  9495:       if (parentDirectory != null && !parentDirectory.isDirectory ()) {  //親ディレクトリがない
  9496:         String parentName = parentDirectory.getPath ();
  9497:         if (parentDirectory.mkdirs ()) {  //親ディレクトリを作る。必要ならば遡って作る。作れた
  9498:           System.out.println (Multilingual.mlnJapanese ?
  9499:                               parentName + " を作りました" :
  9500:                               parentName + " was created");
  9501:         } else {  //作れなかった
  9502:           switch (rscShowError (Multilingual.mlnJapanese ?
  9503:                                 parentName + " を作れません" :
  9504:                                 parentName + " cannot be created",
  9505:                                 RSC_A_MASK | RSC_R_MASK | RSC_I_MASK)) {
  9506:           case RSC_A_MASK:
  9507:             break retry;
  9508:           case RSC_R_MASK:
  9509:             continue retry;
  9510:           }
  9511:         }
  9512:       }
  9513:       if (fileTmp.isFile ()) {  //name.tmpがある。前回異常終了して残骸が残っている場合など
  9514:         if (!fileTmp.delete ()) {  //name.tmpを削除する。削除できない
  9515:           switch (rscShowError (Multilingual.mlnJapanese ?
  9516:                                 nameTmp + " を削除できません" :
  9517:                                 nameTmp + " cannot be deleted",
  9518:                                 RSC_A_MASK | RSC_R_MASK | RSC_I_MASK)) {
  9519:           case RSC_A_MASK:
  9520:             break retry;
  9521:           case RSC_R_MASK:
  9522:             continue retry;
  9523:           }
  9524:         }
  9525:       }
  9526:       try (OutputStream os = name.toLowerCase ().endsWith (".gz") ?
  9527:            new GZIPOutputStream (new BufferedOutputStream (new FileOutputStream (fileTmp))) {
  9528:              {
  9529:                //def.setLevel (Deflater.BEST_COMPRESSION);
  9530:                def.setLevel (Deflater.DEFAULT_COMPRESSION);
  9531:                //def.setLevel (Deflater.BEST_SPEED);
  9532:              }
  9533:            } :
  9534:            new BufferedOutputStream (new FileOutputStream (fileTmp))) {  //name.tmpに書き出す
  9535:         //array[offset..offset+length-1]を書き出す
  9536:         os.write (array, offset, length);
  9537:         //longLength2-length個の0を書き出す
  9538:         //  RandomAccessFile.setLength()は拡張部分の内容が定義されていないので使えない
  9539:         if ((long) length < longLength2) {
  9540:           byte[] buffer = new byte[(int) Math.min (longLength2 - (long) length, (long) (1024 * 1024))];  //最大1MBずつ書き出す
  9541:           Arrays.fill (buffer, 0, buffer.length, (byte) 0);  //念の為
  9542:           long longPosition2 = (long) length;
  9543:           while (longPosition2 < longLength2) {
  9544:             int step = (int) Math.min ((long) buffer.length, longLength2 - longPosition2);
  9545:             os.write (buffer, 0, step);
  9546:             longPosition2 += (long) step;
  9547:           }
  9548:         }
  9549:       } catch (IOException ioe) {
  9550:         switch (rscShowError (Multilingual.mlnJapanese ?
  9551:                               nameTmp + " に書き出せません" :
  9552:                               nameTmp + " cannot be written",
  9553:                               RSC_A_MASK | RSC_R_MASK | RSC_I_MASK)) {
  9554:         case RSC_A_MASK:
  9555:           break retry;
  9556:         case RSC_R_MASK:
  9557:           continue retry;
  9558:         }
  9559:       }
  9560:       if (fileExists && file.isFile ()) {  //同じ名前で内容が異なるファイルがある。リトライでなくなった可能性があるので確認し直す
  9561:         if (fileBak.isFile ()) {  //name.bakがある
  9562:           if (!fileBak.delete ()) {  //name.bakを削除する。削除できない
  9563:             switch (rscShowError (Multilingual.mlnJapanese ?
  9564:                                   nameBak + " を削除できません" :
  9565:                                   nameBak + " cannot be deleted",
  9566:                                   RSC_A_MASK | RSC_R_MASK | RSC_I_MASK)) {
  9567:             case RSC_A_MASK:
  9568:               break retry;
  9569:             case RSC_R_MASK:
  9570:               continue retry;
  9571:             }
  9572:           }
  9573:         }
  9574:         if (!file.renameTo (fileBak)) {  //nameをname.bakにリネームする。リネームできない
  9575:           switch (rscShowError (Multilingual.mlnJapanese ?
  9576:                                 name + " を " + nameBak + " にリネームできません" :
  9577:                                 name + " cannot be renamed to " + nameBak,
  9578:                                 RSC_A_MASK | RSC_R_MASK | RSC_I_MASK)) {
  9579:           case RSC_A_MASK:
  9580:             break retry;
  9581:           case RSC_R_MASK:
  9582:             continue retry;
  9583:           }
  9584:         }
  9585:       }
  9586:       if (fileTmp.renameTo (file)) {  //name.tmpをnameにリネームする。リネームできた
  9587:         if (fileExists) {  //同じ名前のファイルがあった
  9588:           System.out.println (Multilingual.mlnJapanese ?
  9589:                               name + " を更新しました" :
  9590:                               name + " was updated");
  9591:         } else {  //同じ名前のファイルがなかった
  9592:           System.out.println (Multilingual.mlnJapanese ?
  9593:                               name + " を作りました" :
  9594:                               name + " was created");
  9595:         }
  9596:         return true;  //成功
  9597:       } else {  //リネームできない
  9598:         switch (rscShowError (Multilingual.mlnJapanese ?
  9599:                               nameTmp + " を " + name + " にリネームできません" :
  9600:                               nameTmp + " cannot be renamed to " + name,
  9601:                               RSC_A_MASK | RSC_R_MASK | RSC_I_MASK)) {
  9602:         case RSC_A_MASK:
  9603:           break retry;
  9604:         case RSC_R_MASK:
  9605:           continue retry;
  9606:         }
  9607:       }
  9608:       break;
  9609:     }  //retry
  9610:     if (fileExists) {  //同じ名前のファイルがあった
  9611:       System.out.println (Multilingual.mlnJapanese ?
  9612:                           name + " を更新できません" :
  9613:                           name + " cannot be updated");
  9614:     } else {  //同じ名前のファイルがなかった
  9615:       System.out.println (Multilingual.mlnJapanese ?
  9616:                           name + " を作れません" :
  9617:                           name + " cannot be created");
  9618:     }
  9619:     return false;  //失敗
  9620:   }
  9621: 
  9622: 
  9623: 
  9624:   //========================================================================================
  9625:   //$$ISM InputStream
  9626: 
  9627:   public static final Pattern ISM_ZIP_SEPARATOR = Pattern.compile ("(?<=\\.(?:jar|zip))(?:/|\\\\)(?=.)", Pattern.CASE_INSENSITIVE);
  9628: 
  9629:   //in = ismOpen (name)
  9630:   //  InputStreamを開く
  9631:   //  InputStreamを返す
  9632:   //    失敗したときはnullを返す
  9633:   //  ZIPファイルの中のファイルを指定できる
  9634:   //    ZIPファイルの中のファイルはZipInputStreamで開く
  9635:   //    ZIPファイルの中のファイル名は{ZIPファイル名}/{ZIPファイルの中のファイル名}で指定する
  9636:   //    JARファイルもZIPファイルとして開くことができる
  9637:   //  GZIPで圧縮されているファイルを指定できる
  9638:   //    GZIPで圧縮されているファイルはGZIPInputStreamで開く
  9639:   public static InputStream ismOpen (String name) {
  9640:     InputStream in = null;
  9641:     in = ismOpen (name, false);  //ファイルを開く
  9642:     if (in == null && name.indexOf ('/') < 0 && name.indexOf ('\\') < 0) {  //ファイルがないとき
  9643:       in = ismOpen (name, true);  //リソースを開く
  9644:     }
  9645:     return in;
  9646:   }  //ismOpen(String)
  9647:   public static InputStream ismOpen (String name, boolean useGetResource) {
  9648:     boolean gzipped = name.toLowerCase ().endsWith (".gz");  //true=GZIPファイルが指定された
  9649:     String[] zipSplittedName = ISM_ZIP_SEPARATOR.split (name, 2);  //ZIPファイル名とZIPファイルの中のファイル名に分ける
  9650:     String fileName = zipSplittedName[0];  //通常のファイル名またはZIPファイル名
  9651:     String zipEntryName = zipSplittedName.length < 2 ? null : zipSplittedName[1];  //ZIPファイルの中のファイル名
  9652:     InputStream in = null;
  9653:     try {
  9654:       if (useGetResource) {  //getResourceを使うとき
  9655:         if (false) {
  9656:           URL url = XEiJ.class.getResource (fileName);
  9657:           if (url != null) {  //ファイルがある
  9658:             in = url.openStream ();
  9659:           }
  9660:         } else {
  9661:           in = XEiJ.class.getResourceAsStream (fileName);
  9662:         }
  9663:       } else {
  9664:         File file = new File (fileName);
  9665:         if (file.exists ()) {  //ファイルがある
  9666:           in = new FileInputStream (file);
  9667:         }
  9668:       }
  9669:       if (in != null && zipEntryName != null) {  //ZIPファイルの中のファイルが指定されたとき
  9670:         ZipInputStream zin = new ZipInputStream (in);
  9671:         in = null;
  9672:         ZipEntry entry;
  9673:         while ((entry = zin.getNextEntry ()) != null) {  //指定されたファイル名のエントリを探す
  9674:           if (zipEntryName.equals (entry.getName ())) {  //エントリが見つかった
  9675:             in = zin;
  9676:             break;
  9677:           }
  9678:         }
  9679:         if (in == null) {
  9680:           System.out.println (Multilingual.mlnJapanese ? fileName + " の中に " + zipEntryName + " がありません" :
  9681:                               zipEntryName + " does not exist in " + fileName);
  9682:         }
  9683:       }
  9684:       if (in != null && gzipped) {  //GZIPで圧縮されたファイルが指定されたとき
  9685:         in = new GZIPInputStream (in);
  9686:       }
  9687:       if (in != null) {
  9688:         System.out.println (Multilingual.mlnJapanese ? (useGetResource ? "リソースファイル " : "ファイル ") + name + " を読み込みます" :
  9689:                             (useGetResource ? "Reading resource file " : "Reading file ") + name);
  9690:         return new BufferedInputStream (in);
  9691:       }
  9692:     } catch (Exception ioe) {
  9693:       if (prgVerbose) {
  9694:         prgPrintStackTraceOf (ioe);
  9695:       }
  9696:     }
  9697:     System.out.println (Multilingual.mlnJapanese ? (useGetResource ? "リソースファイル " : "ファイル ") + name + " が見つかりません" :
  9698:                         (useGetResource ? "Resource file " : "File ") + name + " is not found");
  9699:     return null;  //失敗
  9700:   }  //ismOpen(String,boolean)
  9701: 
  9702:   //k = ismRead (in, bb, o, l)
  9703:   //  InputStreamからバイトバッファに読み込む
  9704:   //  読み込んだ長さを返す
  9705:   //    エラーのときは-1を返す
  9706:   //  指定されたサイズまたはファイルの末尾まで読み込む
  9707:   //    k=in.read(bb,o,l)は1回で指定されたサイズを読み込めるとは限らない
  9708:   //  ブロックされる可能性があるのでコアの動作中にコアのスレッドから呼ばないほうがよい
  9709:   public static int ismRead (InputStream in, byte[] bb, int o, int l) {
  9710:     try {
  9711:       int k = 0;
  9712:       while (k < l) {
  9713:         int t = in.read (bb, o + k, l - k);
  9714:         if (t < 0) {
  9715:           break;
  9716:         }
  9717:         k += t;
  9718:       }
  9719:       return k;
  9720:     } catch (IOException ioe) {
  9721:       if (prgVerbose) {
  9722:         prgPrintStackTraceOf (ioe);
  9723:       }
  9724:     }
  9725:     return -1;
  9726:   }  //ismRead(InputStream,byte[],int,int)
  9727: 
  9728:   //k = ismSkip (in, l)
  9729:   //  InputStreamを読み飛ばす
  9730:   //  読み飛ばした長さを返す
  9731:   //    エラーのときは-1を返す
  9732:   //  指定されたサイズまたはファイルの末尾まで読み飛ばす
  9733:   //    k=in.skip(l)は1回で指定されたサイズを読み飛ばせるとは限らない
  9734:   //  ブロックされる可能性があるのでコアの動作中にコアのスレッドから呼ばないほうがよい
  9735:   public static int ismSkip (InputStream in, int l) {
  9736:     try {
  9737:       int k = 0;
  9738:       while (k < l) {
  9739:         //skip(long)はファイルの末尾でなくても0を返す可能性があるのでファイルの末尾の判定はread()で行う
  9740:         //skip(long)する前に毎回read()しないとskip()がファイルの末尾で止まらなくなるらしい
  9741:         if (in.read () < 0) {
  9742:           break;
  9743:         }
  9744:         k++;
  9745:         if (k < l) {
  9746:           int t = (int) in.skip ((long) (l - k));
  9747:           if (t < 0) {
  9748:             break;
  9749:           }
  9750:           k += t;
  9751:         }
  9752:       }
  9753:       return k;
  9754:     } catch (IOException ioe) {
  9755:       if (prgVerbose) {
  9756:         prgPrintStackTraceOf (ioe);
  9757:       }
  9758:     }
  9759:     return -1;
  9760:   }  //ismSkip(InputStream,int)
  9761: 
  9762:   //ismClose (in)
  9763:   //  InputStreamを閉じる
  9764:   //  in==nullのときは何もしない
  9765:   //  in.close()でIOExceptionを無視するだけ
  9766:   public static void ismClose (InputStream in) {
  9767:     try {
  9768:       if (in != null) {
  9769:         in.close ();
  9770:       }
  9771:     } catch (IOException ioe) {
  9772:       if (prgVerbose) {
  9773:         prgPrintStackTraceOf (ioe);
  9774:       }
  9775:     }
  9776:   }  //ismClose(InputStream)
  9777: 
  9778:   //length = ismLength (name, maxLength)
  9779:   //  ファイルの長さを数える
  9780:   //  ZIPファイルの中のファイルを指定できる
  9781:   //  GZIPで圧縮されているファイルを指定できる
  9782:   //  -1  ファイルがない
  9783:   public static int ismLength (String name, int maxLength) {
  9784:     int length;
  9785:     InputStream in = ismOpen (name);
  9786:     if (in == null) {  //ファイルがない
  9787:       length = -1;
  9788:     } else {  //ファイルがある
  9789:       length = ismSkip (in, maxLength);
  9790:       ismClose (in);
  9791:     }
  9792:     return length;
  9793:   }  //ismLength(String,int)
  9794: 
  9795:   //success = ismLoad (bb, o, l, names)
  9796:   //  ファイルからバイトバッファに読み込む
  9797:   //  ファイル名を,で区切って複数指定できる
  9798:   //    先頭から順に指定されたサイズまで読み込めるファイルを探す
  9799:   //    1つでも読み込むことができればその時点で成功、1つも読み込めなければ失敗
  9800:   //  成功したときtrueを返す
  9801:   //  ZIPファイルの中のファイルを指定できる
  9802:   //    ZIPファイルの中のファイルはZipInputStreamで開く
  9803:   //    ZIPファイルの中のファイル名は{ZIPファイル名}/{ZIPファイルの中のファイル名}で指定する
  9804:   //    JARファイルもZIPファイルとして開くことができる
  9805:   //  GZIPで圧縮されているファイルを指定できる
  9806:   //    GZIPで圧縮されているファイルはGZIPInputStreamで開く
  9807:   //  ブロックされることがあるのでコアの動作中にコアのスレッドから呼ばないほうがよい
  9808:   public static boolean ismLoad (byte[] bb, int o, int l, String names) {
  9809:     for (String name : names.split (",")) {  //先頭から順に
  9810:       if (name.length () != 0) {  //ファイル名が指定されているとき
  9811:         InputStream in = ismOpen (name);  //開く
  9812:         if (in != null) {  //開けたら
  9813:           int k = ismRead (in, bb, o, l);  //読み込んで
  9814:           ismClose (in);  //閉じる
  9815:           if (k == l) {  //指定されたサイズまで読み込めたら
  9816:             return true;  //成功
  9817:           }
  9818:         }
  9819:       }
  9820:     }
  9821:     return false;  //1つも読み込めなかったので失敗
  9822:   }  //ismLoad(byte[],int,int,String)
  9823: 
  9824:   //success = ismSave (bb, offset, length, path, verbose)
  9825:   //  バイトバッファからファイルに書き出す
  9826:   //  出力範囲がバッファに収まっているとき
  9827:   //    ファイルが既に存在していてファイルサイズと内容が一致しているときは更新しない
  9828:   //  出力範囲がバッファに収まっていないとき
  9829:   //    バッファからはみ出した部分をゼロクリアする
  9830:   //    RandomAccessFileのsetLengthを使うとファイルサイズを簡単に変更できるが、ファイルを伸ばしたときに書き込まれる内容が仕様で定義されていない
  9831:   //    同じ手順で同じ内容のファイルができない可能性があるのは困るので明示的に0を書き込んでクリアする
  9832:   public static boolean ismSave (byte[] bb, int offset, long length, String path, boolean verbose) {
  9833:     if (ISM_ZIP_SEPARATOR.split (path, 2).length != 1) {  //ZIPファイルの中のファイル
  9834:       if (verbose) {
  9835:         pnlExitFullScreen (true);
  9836:         JOptionPane.showMessageDialog (null, Multilingual.mlnJapanese ? path + " に書き出せません" : "Cannot write " + path);
  9837:       }
  9838:       return false;
  9839:     }
  9840:     long step = 0;  //一度にゼロクリアする長さ。0=バッファに収まっている
  9841:     byte[] zz = null;  //ゼロクリア用の配列
  9842:     long pointer = (long) (bb.length - offset);  //バッファから出力できる長さ
  9843:     if (pointer < length) {  //バッファに収まっていない
  9844:       step = Math.min (1024L * 512, length - pointer);  //一度にゼロクリアする長さ。最大512KB
  9845:       zz = new byte[(int) step];  //ゼロクリア用の配列
  9846:       Arrays.fill (zz, (byte) 0);
  9847:     }
  9848:     //ファイル
  9849:     File file = new File (path);  //ファイル
  9850:     //ファイルが既に存在しているときはファイルサイズと内容が一致しているかどうか確認する
  9851:     if (step == 0 &&  //バッファに収まっている
  9852:         file.exists () && file.length () == length) {  //ファイルサイズが一致している
  9853:       //ファイルを読み込む
  9854:       if (length == 0L) {  //ファイルサイズが0で一致しているので成功
  9855:         return true;
  9856:       }
  9857:       InputStream in = ismOpen (path);
  9858:       if (in != null) {
  9859:         int l = (int) length;  //バッファに収まっているのだからintの範囲内
  9860:         byte[] tt = new byte[l];
  9861:         int k = ismRead (in, tt, 0, l);
  9862:         ismClose (in);
  9863:         if (k == l &&
  9864:             Arrays.equals (tt, bb.length == l ? bb : Arrays.copyOfRange (bb, offset, offset + l))) {  //内容が一致している
  9865:           return true;  //更新する必要がないので成功
  9866:         }
  9867:       }
  9868:     }  //check
  9869:     // *.tmpと*.bak
  9870:     String pathTmp = path + ".tmp";  // *.tmp
  9871:     String pathBak = path + ".bak";  // *.bak
  9872:     File fileTmp = new File (pathTmp);  // *.tmp
  9873:     File fileBak = new File (pathBak);  // *.bak
  9874:     // *.tmpを削除する
  9875:     if (fileTmp.exists ()) {  // *.tmpがあるとき
  9876:       if (!fileTmp.delete ()) {  // *.tmpを削除する
  9877:         if (verbose) {
  9878:           pnlExitFullScreen (true);
  9879:           JOptionPane.showMessageDialog (null, Multilingual.mlnJapanese ? pathTmp + " を削除できません" : "Cannot delete " + pathTmp);
  9880:         }
  9881:         return false;
  9882:       }
  9883:     }
  9884:     // *.tmpに書き出す
  9885:     try (OutputStream out = path.toLowerCase ().endsWith (".gz") ?  //pathの末尾が".gz"のときpathTmpの末尾は".gz.tmp"であることに注意
  9886:          new GZIPOutputStream (new BufferedOutputStream (new FileOutputStream (fileTmp))) {
  9887:            {
  9888:              //def.setLevel (Deflater.BEST_COMPRESSION);
  9889:              def.setLevel (Deflater.DEFAULT_COMPRESSION);
  9890:              //def.setLevel (Deflater.BEST_SPEED);
  9891:            }
  9892:          } :
  9893:          new BufferedOutputStream (new FileOutputStream (fileTmp))) {  //try-with-resourcesは1.7から
  9894:       if (step == 0) {  //バッファに収まっている
  9895:         out.write (bb, offset, (int) length);  //OutputStreamのwriteの返り値はvoid。エラーが出なければ1回で最後まで書き出される
  9896:       } else {  //バッファに収まっていない
  9897:         out.write (bb, offset, (int) pointer);  //バッファから出力できる範囲
  9898:         for (; pointer < length; pointer += step) {
  9899:           out.write (zz, 0, (int) Math.min (step, length - pointer));  //バッファから出力できない範囲
  9900:         }
  9901:       }
  9902:     } catch (IOException ioe) {
  9903:       if (verbose) {
  9904:         prgPrintStackTraceOf (ioe);
  9905:         pnlExitFullScreen (true);
  9906:         JOptionPane.showMessageDialog (null, Multilingual.mlnJapanese ? pathTmp + " に書き出せません" : "Cannot write " + pathTmp);
  9907:       }
  9908:       return false;
  9909:     }
  9910:     //ファイルを*.bakにリネームする
  9911:     //  javaのFileのrenameToはPerlと違って上書きしてくれないので明示的に削除またはリネームする必要がある
  9912:     if (file.exists ()) {  //ファイルがあるとき
  9913:       if (fileBak.exists ()) {  // *.bakがあるとき
  9914:         if (!fileBak.delete ()) {  // *.bakを削除する
  9915:           if (verbose) {
  9916:             pnlExitFullScreen (true);
  9917:             JOptionPane.showMessageDialog (null, Multilingual.mlnJapanese ? pathBak + " を削除できません" : "Cannot delete " + pathBak);
  9918:           }
  9919:           return false;
  9920:         }
  9921:       }
  9922:       if (!file.renameTo (fileBak)) {  //ファイルを*.bakにリネームする
  9923:         if (verbose) {
  9924:           pnlExitFullScreen (true);
  9925:           JOptionPane.showMessageDialog (
  9926:             null, Multilingual.mlnJapanese ? path + " を " + pathBak + " にリネームできません" : "Cannot rename " + path + " to " + pathBak);
  9927:         }
  9928:         return false;
  9929:       }
  9930:     }
  9931:     // *.tmpをファイルにリネームする
  9932:     //  javaのFileのrenameToはPerlと違って上書きしてくれないので明示的に削除またはリネームする必要がある
  9933:     if (!fileTmp.renameTo (file)) {  // *.tmpをファイルにリネームする
  9934:       if (verbose) {
  9935:         pnlExitFullScreen (true);
  9936:         JOptionPane.showMessageDialog (
  9937:           null, Multilingual.mlnJapanese ? pathTmp + " を " + path + " にリネームできません" : "Cannot rename " + pathTmp + " to " + path);
  9938:       }
  9939:       return false;
  9940:     }
  9941:     return true;
  9942:   }  //ismSave(byte[],int,long,String,boolean)
  9943: 
  9944: 
  9945: 
  9946:   //========================================================================================
  9947:   //$$FMT フォーマット変換
  9948:   //  Formatterは遅いので自前で展開する
  9949: 
  9950:   public static final char[] FMT_TEMP = new char[32];
  9951: 
  9952:   //--------------------------------------------------------------------------------
  9953:   //2進数変換
  9954:   //  ainNは'.'と'*'、binNは'0'と'1'に変換する
  9955:   //
  9956:   //  x          00 01
  9957:   //  x<<2       00 04
  9958:   //  x<<2&4     00 04
  9959:   //  x<<2&4^46  2e 2a
  9960:   //              .  *
  9961: 
  9962:   public static final char[] FMT_AIN4_BASE = ".......*..*...**.*...*.*.**..****...*..**.*.*.****..**.****.****".toCharArray ();
  9963:   public static final char[] FMT_BIN4_BASE = "0000000100100011010001010110011110001001101010111100110111101111".toCharArray ();
  9964: 
  9965:   //fmtAin4 (a, o, x)
  9966:   //fmtBin4 (a, o, x)
  9967:   //s = fmtAin4 (x)
  9968:   //s = fmtBin4 (x)
  9969:   //sb = fmtAin4 (sb, x)
  9970:   //sb = fmtBin4 (sb, x)
  9971:   //  4桁2進数変換
  9972:   public static void fmtAin4 (char[] a, int o, int x) {
  9973:     a[o     ] = (char) (x >>  1 & 4 ^ 46);
  9974:     a[o +  1] = (char) (x       & 4 ^ 46);
  9975:     a[o +  2] = (char) (x <<  1 & 4 ^ 46);
  9976:     a[o +  3] = (char) (x <<  2 & 4 ^ 46);
  9977:   }  //fmtAin4(char[],int,int)
  9978:   public static void fmtBin4 (char[] a, int o, int x) {
  9979:     a[o     ] = (char) (x >>>  3 & 1 | 48);
  9980:     a[o +  1] = (char) (x >>>  2 & 1 | 48);
  9981:     a[o +  2] = (char) (x >>>  1 & 1 | 48);
  9982:     a[o +  3] = (char) (x        & 1 | 48);
  9983:   }  //fmtBin4(char[],int,int)
  9984:   public static String fmtAin4 (int x) {
  9985:     return String.valueOf (FMT_AIN4_BASE, (x & 15) << 2, 4);
  9986:   }  //fmtAin4(int)
  9987:   public static String fmtBin4 (int x) {
  9988:     return String.valueOf (FMT_BIN4_BASE, (x & 15) << 2, 4);
  9989:   }  //fmtBin4(int)
  9990:   public static StringBuilder fmtAin4 (StringBuilder sb, int x) {
  9991:     return sb.append (FMT_AIN4_BASE, (x & 15) << 2, 6);
  9992:   }  //fmtAin4(StringBuilder,int)
  9993:   public static StringBuilder fmtBin4 (StringBuilder sb, int x) {
  9994:     return sb.append (FMT_BIN4_BASE, (x & 15) << 2, 6);
  9995:   }  //fmtBin4(StringBuilder,int)
  9996: 
  9997:   //fmtAin6 (a, o, x)
  9998:   //fmtBin6 (a, o, x)
  9999:   //s = fmtAin6 (x)
 10000:   //s = fmtBin6 (x)
 10001:   //sb = fmtAin6 (sb, x)
 10002:   //sb = fmtBin6 (sb, x)
 10003:   //  6桁2進数変換
 10004:   public static void fmtAin6 (char[] a, int o, int x) {
 10005:     a[o     ] = (char) (x >>  3 & 4 ^ 46);
 10006:     a[o +  1] = (char) (x >>  2 & 4 ^ 46);
 10007:     a[o +  2] = (char) (x >>  1 & 4 ^ 46);
 10008:     a[o +  3] = (char) (x       & 4 ^ 46);
 10009:     a[o +  4] = (char) (x <<  1 & 4 ^ 46);
 10010:     a[o +  5] = (char) (x <<  2 & 4 ^ 46);
 10011:   }  //fmtAin6(char[],int,int)
 10012:   public static void fmtBin6 (char[] a, int o, int x) {
 10013:     a[o     ] = (char) (x >>>  5 & 1 | 48);
 10014:     a[o +  1] = (char) (x >>>  4 & 1 | 48);
 10015:     a[o +  2] = (char) (x >>>  3 & 1 | 48);
 10016:     a[o +  3] = (char) (x >>>  2 & 1 | 48);
 10017:     a[o +  4] = (char) (x >>>  1 & 1 | 48);
 10018:     a[o +  5] = (char) (x        & 1 | 48);
 10019:   }  //fmtBin6(char[],int,int)
 10020:   public static String fmtAin6 (int x) {
 10021:     FMT_TEMP[ 0] = (char) (x >>  3 & 4 ^ 46);
 10022:     FMT_TEMP[ 1] = (char) (x >>  2 & 4 ^ 46);
 10023:     FMT_TEMP[ 2] = (char) (x >>  1 & 4 ^ 46);
 10024:     FMT_TEMP[ 3] = (char) (x       & 4 ^ 46);
 10025:     FMT_TEMP[ 4] = (char) (x <<  1 & 4 ^ 46);
 10026:     FMT_TEMP[ 5] = (char) (x <<  2 & 4 ^ 46);
 10027:     return String.valueOf (FMT_TEMP, 0, 6);
 10028:   }  //fmtAin6(int)
 10029:   public static String fmtBin6 (int x) {
 10030:     FMT_TEMP[ 0] = (char) (x >>>  5 & 1 | 48);
 10031:     FMT_TEMP[ 1] = (char) (x >>>  4 & 1 | 48);
 10032:     FMT_TEMP[ 2] = (char) (x >>>  3 & 1 | 48);
 10033:     FMT_TEMP[ 3] = (char) (x >>>  2 & 1 | 48);
 10034:     FMT_TEMP[ 4] = (char) (x >>>  1 & 1 | 48);
 10035:     FMT_TEMP[ 5] = (char) (x        & 1 | 48);
 10036:     return String.valueOf (FMT_TEMP, 0, 6);
 10037:   }  //fmtBin6(int)
 10038:   public static StringBuilder fmtAin6 (StringBuilder sb, int x) {
 10039:     FMT_TEMP[ 0] = (char) (x >>  3 & 4 ^ 46);
 10040:     FMT_TEMP[ 1] = (char) (x >>  2 & 4 ^ 46);
 10041:     FMT_TEMP[ 2] = (char) (x >>  1 & 4 ^ 46);
 10042:     FMT_TEMP[ 3] = (char) (x       & 4 ^ 46);
 10043:     FMT_TEMP[ 4] = (char) (x <<  1 & 4 ^ 46);
 10044:     FMT_TEMP[ 5] = (char) (x <<  2 & 4 ^ 46);
 10045:     return sb.append (FMT_TEMP, 0, 6);
 10046:   }  //fmtAin6(StringBuilder,int)
 10047:   public static StringBuilder fmtBin6 (StringBuilder sb, int x) {
 10048:     FMT_TEMP[ 0] = (char) (x >>>  5 & 1 | 48);
 10049:     FMT_TEMP[ 1] = (char) (x >>>  4 & 1 | 48);
 10050:     FMT_TEMP[ 2] = (char) (x >>>  3 & 1 | 48);
 10051:     FMT_TEMP[ 3] = (char) (x >>>  2 & 1 | 48);
 10052:     FMT_TEMP[ 4] = (char) (x >>>  1 & 1 | 48);
 10053:     FMT_TEMP[ 5] = (char) (x        & 1 | 48);
 10054:     return sb.append (FMT_TEMP, 0, 6);
 10055:   }  //fmtBin6(StringBuilder,int)
 10056: 
 10057:   //fmtAin8 (a, o, x)
 10058:   //fmtBin8 (a, o, x)
 10059:   //s = fmtAin8 (x)
 10060:   //s = fmtBin8 (x)
 10061:   //sb = fmtAin8 (sb, x)
 10062:   //sb = fmtBin8 (sb, x)
 10063:   //  8桁2進数変換
 10064:   public static void fmtAin8 (char[] a, int o, int x) {
 10065:     a[o     ] = (char) (x >>  5 & 4 ^ 46);
 10066:     a[o +  1] = (char) (x >>  4 & 4 ^ 46);
 10067:     a[o +  2] = (char) (x >>  3 & 4 ^ 46);
 10068:     a[o +  3] = (char) (x >>  2 & 4 ^ 46);
 10069:     a[o +  4] = (char) (x >>  1 & 4 ^ 46);
 10070:     a[o +  5] = (char) (x       & 4 ^ 46);
 10071:     a[o +  6] = (char) (x <<  1 & 4 ^ 46);
 10072:     a[o +  7] = (char) (x <<  2 & 4 ^ 46);
 10073:   }  //fmtAin8(char[],int,int)
 10074:   public static void fmtBin8 (char[] a, int o, int x) {
 10075:     a[o     ] = (char) (x >>>  7 & 1 | 48);
 10076:     a[o +  1] = (char) (x >>>  6 & 1 | 48);
 10077:     a[o +  2] = (char) (x >>>  5 & 1 | 48);
 10078:     a[o +  3] = (char) (x >>>  4 & 1 | 48);
 10079:     a[o +  4] = (char) (x >>>  3 & 1 | 48);
 10080:     a[o +  5] = (char) (x >>>  2 & 1 | 48);
 10081:     a[o +  6] = (char) (x >>>  1 & 1 | 48);
 10082:     a[o +  7] = (char) (x        & 1 | 48);
 10083:   }  //fmtBin8(char[],int,int)
 10084:   public static String fmtAin8 (int x) {
 10085:     FMT_TEMP[ 0] = (char) (x >>  5 & 4 ^ 46);
 10086:     FMT_TEMP[ 1] = (char) (x >>  4 & 4 ^ 46);
 10087:     FMT_TEMP[ 2] = (char) (x >>  3 & 4 ^ 46);
 10088:     FMT_TEMP[ 3] = (char) (x >>  2 & 4 ^ 46);
 10089:     FMT_TEMP[ 4] = (char) (x >>  1 & 4 ^ 46);
 10090:     FMT_TEMP[ 5] = (char) (x       & 4 ^ 46);
 10091:     FMT_TEMP[ 6] = (char) (x <<  1 & 4 ^ 46);
 10092:     FMT_TEMP[ 7] = (char) (x <<  2 & 4 ^ 46);
 10093:     return String.valueOf (FMT_TEMP, 0, 8);
 10094:   }  //fmtAin8(int)
 10095:   public static String fmtBin8 (int x) {
 10096:     FMT_TEMP[ 0] = (char) (x >>>  7 & 1 | 48);
 10097:     FMT_TEMP[ 1] = (char) (x >>>  6 & 1 | 48);
 10098:     FMT_TEMP[ 2] = (char) (x >>>  5 & 1 | 48);
 10099:     FMT_TEMP[ 3] = (char) (x >>>  4 & 1 | 48);
 10100:     FMT_TEMP[ 4] = (char) (x >>>  3 & 1 | 48);
 10101:     FMT_TEMP[ 5] = (char) (x >>>  2 & 1 | 48);
 10102:     FMT_TEMP[ 6] = (char) (x >>>  1 & 1 | 48);
 10103:     FMT_TEMP[ 7] = (char) (x        & 1 | 48);
 10104:     return String.valueOf (FMT_TEMP, 0, 8);
 10105:   }  //fmtBin8(int)
 10106:   public static StringBuilder fmtAin8 (StringBuilder sb, int x) {
 10107:     FMT_TEMP[ 0] = (char) (x >>  5 & 4 ^ 46);
 10108:     FMT_TEMP[ 1] = (char) (x >>  4 & 4 ^ 46);
 10109:     FMT_TEMP[ 2] = (char) (x >>  3 & 4 ^ 46);
 10110:     FMT_TEMP[ 3] = (char) (x >>  2 & 4 ^ 46);
 10111:     FMT_TEMP[ 4] = (char) (x >>  1 & 4 ^ 46);
 10112:     FMT_TEMP[ 5] = (char) (x       & 4 ^ 46);
 10113:     FMT_TEMP[ 6] = (char) (x <<  1 & 4 ^ 46);
 10114:     FMT_TEMP[ 7] = (char) (x <<  2 & 4 ^ 46);
 10115:     return sb.append (FMT_TEMP, 0, 8);
 10116:   }  //fmtAin8(StringBuilder,int)
 10117:   public static StringBuilder fmtBin8 (StringBuilder sb, int x) {
 10118:     FMT_TEMP[ 0] = (char) (x >>>  7 & 1 | 48);
 10119:     FMT_TEMP[ 1] = (char) (x >>>  6 & 1 | 48);
 10120:     FMT_TEMP[ 2] = (char) (x >>>  5 & 1 | 48);
 10121:     FMT_TEMP[ 3] = (char) (x >>>  4 & 1 | 48);
 10122:     FMT_TEMP[ 4] = (char) (x >>>  3 & 1 | 48);
 10123:     FMT_TEMP[ 5] = (char) (x >>>  2 & 1 | 48);
 10124:     FMT_TEMP[ 6] = (char) (x >>>  1 & 1 | 48);
 10125:     FMT_TEMP[ 7] = (char) (x        & 1 | 48);
 10126:     return sb.append (FMT_TEMP, 0, 8);
 10127:   }  //fmtBin8(StringBuilder,int)
 10128: 
 10129:   //fmtAin12 (a, o, x)
 10130:   //fmtBin12 (a, o, x)
 10131:   //s = fmtAin12 (x)
 10132:   //s = fmtBin12 (x)
 10133:   //sb = fmtAin12 (sb, x)
 10134:   //sb = fmtBin12 (sb, x)
 10135:   //  12桁2進数変換
 10136:   public static void fmtAin12 (char[] a, int o, int x) {
 10137:     a[o     ] = (char) (x >>  9 & 4 ^ 46);
 10138:     a[o +  1] = (char) (x >>  8 & 4 ^ 46);
 10139:     a[o +  2] = (char) (x >>  7 & 4 ^ 46);
 10140:     a[o +  3] = (char) (x >>  6 & 4 ^ 46);
 10141:     a[o +  4] = (char) (x >>  5 & 4 ^ 46);
 10142:     a[o +  5] = (char) (x >>  4 & 4 ^ 46);
 10143:     a[o +  6] = (char) (x >>  3 & 4 ^ 46);
 10144:     a[o +  7] = (char) (x >>  2 & 4 ^ 46);
 10145:     a[o +  8] = (char) (x >>  1 & 4 ^ 46);
 10146:     a[o +  9] = (char) (x       & 4 ^ 46);
 10147:     a[o + 10] = (char) (x <<  1 & 4 ^ 46);
 10148:     a[o + 11] = (char) (x <<  2 & 4 ^ 46);
 10149:   }  //fmtAin12(char[],int,int)
 10150:   public static void fmtBin12 (char[] a, int o, int x) {
 10151:     a[o     ] = (char) (x >>> 11 & 1 | 48);
 10152:     a[o +  1] = (char) (x >>> 10 & 1 | 48);
 10153:     a[o +  2] = (char) (x >>>  9 & 1 | 48);
 10154:     a[o +  3] = (char) (x >>>  8 & 1 | 48);
 10155:     a[o +  4] = (char) (x >>>  7 & 1 | 48);
 10156:     a[o +  5] = (char) (x >>>  6 & 1 | 48);
 10157:     a[o +  6] = (char) (x >>>  5 & 1 | 48);
 10158:     a[o +  7] = (char) (x >>>  4 & 1 | 48);
 10159:     a[o +  8] = (char) (x >>>  3 & 1 | 48);
 10160:     a[o +  9] = (char) (x >>>  2 & 1 | 48);
 10161:     a[o + 10] = (char) (x >>>  1 & 1 | 48);
 10162:     a[o + 11] = (char) (x        & 1 | 48);
 10163:   }  //fmtBin12(char[],int,int)
 10164:   public static String fmtAin12 (int x) {
 10165:     FMT_TEMP[ 0] = (char) (x >>  9 & 4 ^ 46);
 10166:     FMT_TEMP[ 1] = (char) (x >>  8 & 4 ^ 46);
 10167:     FMT_TEMP[ 2] = (char) (x >>  7 & 4 ^ 46);
 10168:     FMT_TEMP[ 3] = (char) (x >>  6 & 4 ^ 46);
 10169:     FMT_TEMP[ 4] = (char) (x >>  5 & 4 ^ 46);
 10170:     FMT_TEMP[ 5] = (char) (x >>  4 & 4 ^ 46);
 10171:     FMT_TEMP[ 6] = (char) (x >>  3 & 4 ^ 46);
 10172:     FMT_TEMP[ 7] = (char) (x >>  2 & 4 ^ 46);
 10173:     FMT_TEMP[ 8] = (char) (x >>  1 & 4 ^ 46);
 10174:     FMT_TEMP[ 9] = (char) (x       & 4 ^ 46);
 10175:     FMT_TEMP[10] = (char) (x <<  1 & 4 ^ 46);
 10176:     FMT_TEMP[11] = (char) (x <<  2 & 4 ^ 46);
 10177:     return String.valueOf (FMT_TEMP, 0, 12);
 10178:   }  //fmtAin12(int)
 10179:   public static String fmtBin12 (int x) {
 10180:     FMT_TEMP[ 0] = (char) (x >>> 11 & 1 | 48);
 10181:     FMT_TEMP[ 1] = (char) (x >>> 10 & 1 | 48);
 10182:     FMT_TEMP[ 2] = (char) (x >>>  9 & 1 | 48);
 10183:     FMT_TEMP[ 3] = (char) (x >>>  8 & 1 | 48);
 10184:     FMT_TEMP[ 4] = (char) (x >>>  7 & 1 | 48);
 10185:     FMT_TEMP[ 5] = (char) (x >>>  6 & 1 | 48);
 10186:     FMT_TEMP[ 6] = (char) (x >>>  5 & 1 | 48);
 10187:     FMT_TEMP[ 7] = (char) (x >>>  4 & 1 | 48);
 10188:     FMT_TEMP[ 8] = (char) (x >>>  3 & 1 | 48);
 10189:     FMT_TEMP[ 9] = (char) (x >>>  2 & 1 | 48);
 10190:     FMT_TEMP[10] = (char) (x >>>  1 & 1 | 48);
 10191:     FMT_TEMP[11] = (char) (x        & 1 | 48);
 10192:     return String.valueOf (FMT_TEMP, 0, 12);
 10193:   }  //fmtBin12(int)
 10194:   public static StringBuilder fmtAin12 (StringBuilder sb, int x) {
 10195:     FMT_TEMP[ 0] = (char) (x >>  9 & 4 ^ 46);
 10196:     FMT_TEMP[ 1] = (char) (x >>  8 & 4 ^ 46);
 10197:     FMT_TEMP[ 2] = (char) (x >>  7 & 4 ^ 46);
 10198:     FMT_TEMP[ 3] = (char) (x >>  6 & 4 ^ 46);
 10199:     FMT_TEMP[ 4] = (char) (x >>  5 & 4 ^ 46);
 10200:     FMT_TEMP[ 5] = (char) (x >>  4 & 4 ^ 46);
 10201:     FMT_TEMP[ 6] = (char) (x >>  3 & 4 ^ 46);
 10202:     FMT_TEMP[ 7] = (char) (x >>  2 & 4 ^ 46);
 10203:     FMT_TEMP[ 8] = (char) (x >>  1 & 4 ^ 46);
 10204:     FMT_TEMP[ 9] = (char) (x       & 4 ^ 46);
 10205:     FMT_TEMP[10] = (char) (x <<  1 & 4 ^ 46);
 10206:     FMT_TEMP[11] = (char) (x <<  2 & 4 ^ 46);
 10207:     return sb.append (FMT_TEMP, 0, 12);
 10208:   }  //fmtAin12(StringBuilder,int)
 10209:   public static StringBuilder fmtBin12 (StringBuilder sb, int x) {
 10210:     FMT_TEMP[ 0] = (char) (x >>> 11 & 1 | 48);
 10211:     FMT_TEMP[ 1] = (char) (x >>> 10 & 1 | 48);
 10212:     FMT_TEMP[ 2] = (char) (x >>>  9 & 1 | 48);
 10213:     FMT_TEMP[ 3] = (char) (x >>>  8 & 1 | 48);
 10214:     FMT_TEMP[ 4] = (char) (x >>>  7 & 1 | 48);
 10215:     FMT_TEMP[ 5] = (char) (x >>>  6 & 1 | 48);
 10216:     FMT_TEMP[ 6] = (char) (x >>>  5 & 1 | 48);
 10217:     FMT_TEMP[ 7] = (char) (x >>>  4 & 1 | 48);
 10218:     FMT_TEMP[ 8] = (char) (x >>>  3 & 1 | 48);
 10219:     FMT_TEMP[ 9] = (char) (x >>>  2 & 1 | 48);
 10220:     FMT_TEMP[10] = (char) (x >>>  1 & 1 | 48);
 10221:     FMT_TEMP[11] = (char) (x        & 1 | 48);
 10222:     return sb.append (FMT_TEMP, 0, 12);
 10223:   }  //fmtBin12(StringBuilder,int)
 10224: 
 10225:   //fmtAin16 (a, o, x)
 10226:   //fmtBin16 (a, o, x)
 10227:   //s = fmtAin16 (x)
 10228:   //s = fmtBin16 (x)
 10229:   //sb = fmtAin16 (sb, x)
 10230:   //sb = fmtBin16 (sb, x)
 10231:   //  16桁2進数変換
 10232:   public static void fmtAin16 (char[] a, int o, int x) {
 10233:     a[o     ] = (char) (x >> 13 & 4 ^ 46);
 10234:     a[o +  1] = (char) (x >> 12 & 4 ^ 46);
 10235:     a[o +  2] = (char) (x >> 11 & 4 ^ 46);
 10236:     a[o +  3] = (char) (x >> 10 & 4 ^ 46);
 10237:     a[o +  4] = (char) (x >>  9 & 4 ^ 46);
 10238:     a[o +  5] = (char) (x >>  8 & 4 ^ 46);
 10239:     a[o +  6] = (char) (x >>  7 & 4 ^ 46);
 10240:     a[o +  7] = (char) (x >>  6 & 4 ^ 46);
 10241:     a[o +  8] = (char) (x >>  5 & 4 ^ 46);
 10242:     a[o +  9] = (char) (x >>  4 & 4 ^ 46);
 10243:     a[o + 10] = (char) (x >>  3 & 4 ^ 46);
 10244:     a[o + 11] = (char) (x >>  2 & 4 ^ 46);
 10245:     a[o + 12] = (char) (x >>  1 & 4 ^ 46);
 10246:     a[o + 13] = (char) (x       & 4 ^ 46);
 10247:     a[o + 14] = (char) (x <<  1 & 4 ^ 46);
 10248:     a[o + 15] = (char) (x <<  2 & 4 ^ 46);
 10249:   }  //fmtAin16(char[],int,int)
 10250:   public static void fmtBin16 (char[] a, int o, int x) {
 10251:     a[o     ] = (char) (x >>> 15 & 1 | 48);
 10252:     a[o +  1] = (char) (x >>> 14 & 1 | 48);
 10253:     a[o +  2] = (char) (x >>> 13 & 1 | 48);
 10254:     a[o +  3] = (char) (x >>> 12 & 1 | 48);
 10255:     a[o +  4] = (char) (x >>> 11 & 1 | 48);
 10256:     a[o +  5] = (char) (x >>> 10 & 1 | 48);
 10257:     a[o +  6] = (char) (x >>>  9 & 1 | 48);
 10258:     a[o +  7] = (char) (x >>>  8 & 1 | 48);
 10259:     a[o +  8] = (char) (x >>>  7 & 1 | 48);
 10260:     a[o +  9] = (char) (x >>>  6 & 1 | 48);
 10261:     a[o + 10] = (char) (x >>>  5 & 1 | 48);
 10262:     a[o + 11] = (char) (x >>>  4 & 1 | 48);
 10263:     a[o + 12] = (char) (x >>>  3 & 1 | 48);
 10264:     a[o + 13] = (char) (x >>>  2 & 1 | 48);
 10265:     a[o + 14] = (char) (x >>>  1 & 1 | 48);
 10266:     a[o + 15] = (char) (x        & 1 | 48);
 10267:   }  //fmtBin16(char[],int,int)
 10268:   public static String fmtAin16 (int x) {
 10269:     FMT_TEMP[ 0] = (char) (x >> 13 & 4 ^ 46);
 10270:     FMT_TEMP[ 1] = (char) (x >> 12 & 4 ^ 46);
 10271:     FMT_TEMP[ 2] = (char) (x >> 11 & 4 ^ 46);
 10272:     FMT_TEMP[ 3] = (char) (x >> 10 & 4 ^ 46);
 10273:     FMT_TEMP[ 4] = (char) (x >>  9 & 4 ^ 46);
 10274:     FMT_TEMP[ 5] = (char) (x >>  8 & 4 ^ 46);
 10275:     FMT_TEMP[ 6] = (char) (x >>  7 & 4 ^ 46);
 10276:     FMT_TEMP[ 7] = (char) (x >>  6 & 4 ^ 46);
 10277:     FMT_TEMP[ 8] = (char) (x >>  5 & 4 ^ 46);
 10278:     FMT_TEMP[ 9] = (char) (x >>  4 & 4 ^ 46);
 10279:     FMT_TEMP[10] = (char) (x >>  3 & 4 ^ 46);
 10280:     FMT_TEMP[11] = (char) (x >>  2 & 4 ^ 46);
 10281:     FMT_TEMP[12] = (char) (x >>  1 & 4 ^ 46);
 10282:     FMT_TEMP[13] = (char) (x       & 4 ^ 46);
 10283:     FMT_TEMP[14] = (char) (x <<  1 & 4 ^ 46);
 10284:     FMT_TEMP[15] = (char) (x <<  2 & 4 ^ 46);
 10285:     return String.valueOf (FMT_TEMP, 0, 16);
 10286:   }  //fmtAin16(int)
 10287:   public static String fmtBin16 (int x) {
 10288:     FMT_TEMP[ 0] = (char) (x >>> 15 & 1 | 48);
 10289:     FMT_TEMP[ 1] = (char) (x >>> 14 & 1 | 48);
 10290:     FMT_TEMP[ 2] = (char) (x >>> 13 & 1 | 48);
 10291:     FMT_TEMP[ 3] = (char) (x >>> 12 & 1 | 48);
 10292:     FMT_TEMP[ 4] = (char) (x >>> 11 & 1 | 48);
 10293:     FMT_TEMP[ 5] = (char) (x >>> 10 & 1 | 48);
 10294:     FMT_TEMP[ 6] = (char) (x >>>  9 & 1 | 48);
 10295:     FMT_TEMP[ 7] = (char) (x >>>  8 & 1 | 48);
 10296:     FMT_TEMP[ 8] = (char) (x >>>  7 & 1 | 48);
 10297:     FMT_TEMP[ 9] = (char) (x >>>  6 & 1 | 48);
 10298:     FMT_TEMP[10] = (char) (x >>>  5 & 1 | 48);
 10299:     FMT_TEMP[11] = (char) (x >>>  4 & 1 | 48);
 10300:     FMT_TEMP[12] = (char) (x >>>  3 & 1 | 48);
 10301:     FMT_TEMP[13] = (char) (x >>>  2 & 1 | 48);
 10302:     FMT_TEMP[14] = (char) (x >>>  1 & 1 | 48);
 10303:     FMT_TEMP[15] = (char) (x        & 1 | 48);
 10304:     return String.valueOf (FMT_TEMP, 0, 16);
 10305:   }  //fmtBin16(int)
 10306:   public static StringBuilder fmtAin16 (StringBuilder sb, int x) {
 10307:     FMT_TEMP[ 0] = (char) (x >> 13 & 4 ^ 46);
 10308:     FMT_TEMP[ 1] = (char) (x >> 12 & 4 ^ 46);
 10309:     FMT_TEMP[ 2] = (char) (x >> 11 & 4 ^ 46);
 10310:     FMT_TEMP[ 3] = (char) (x >> 10 & 4 ^ 46);
 10311:     FMT_TEMP[ 4] = (char) (x >>  9 & 4 ^ 46);
 10312:     FMT_TEMP[ 5] = (char) (x >>  8 & 4 ^ 46);
 10313:     FMT_TEMP[ 6] = (char) (x >>  7 & 4 ^ 46);
 10314:     FMT_TEMP[ 7] = (char) (x >>  6 & 4 ^ 46);
 10315:     FMT_TEMP[ 8] = (char) (x >>  5 & 4 ^ 46);
 10316:     FMT_TEMP[ 9] = (char) (x >>  4 & 4 ^ 46);
 10317:     FMT_TEMP[10] = (char) (x >>  3 & 4 ^ 46);
 10318:     FMT_TEMP[11] = (char) (x >>  2 & 4 ^ 46);
 10319:     FMT_TEMP[12] = (char) (x >>  1 & 4 ^ 46);
 10320:     FMT_TEMP[13] = (char) (x       & 4 ^ 46);
 10321:     FMT_TEMP[14] = (char) (x <<  1 & 4 ^ 46);
 10322:     FMT_TEMP[15] = (char) (x <<  2 & 4 ^ 46);
 10323:     return sb.append (FMT_TEMP, 0, 16);
 10324:   }  //fmtAin16(StringBuilder,int)
 10325:   public static StringBuilder fmtBin16 (StringBuilder sb, int x) {
 10326:     FMT_TEMP[ 0] = (char) (x >>> 15 & 1 | 48);
 10327:     FMT_TEMP[ 1] = (char) (x >>> 14 & 1 | 48);
 10328:     FMT_TEMP[ 2] = (char) (x >>> 13 & 1 | 48);
 10329:     FMT_TEMP[ 3] = (char) (x >>> 12 & 1 | 48);
 10330:     FMT_TEMP[ 4] = (char) (x >>> 11 & 1 | 48);
 10331:     FMT_TEMP[ 5] = (char) (x >>> 10 & 1 | 48);
 10332:     FMT_TEMP[ 6] = (char) (x >>>  9 & 1 | 48);
 10333:     FMT_TEMP[ 7] = (char) (x >>>  8 & 1 | 48);
 10334:     FMT_TEMP[ 8] = (char) (x >>>  7 & 1 | 48);
 10335:     FMT_TEMP[ 9] = (char) (x >>>  6 & 1 | 48);
 10336:     FMT_TEMP[10] = (char) (x >>>  5 & 1 | 48);
 10337:     FMT_TEMP[11] = (char) (x >>>  4 & 1 | 48);
 10338:     FMT_TEMP[12] = (char) (x >>>  3 & 1 | 48);
 10339:     FMT_TEMP[13] = (char) (x >>>  2 & 1 | 48);
 10340:     FMT_TEMP[14] = (char) (x >>>  1 & 1 | 48);
 10341:     FMT_TEMP[15] = (char) (x        & 1 | 48);
 10342:     return sb.append (FMT_TEMP, 0, 16);
 10343:   }  //fmtBin16(StringBuilder,int)
 10344: 
 10345:   //fmtAin24 (a, o, x)
 10346:   //fmtBin24 (a, o, x)
 10347:   //s = fmtAin24 (x)
 10348:   //s = fmtBin24 (x)
 10349:   //sb = fmtAin24 (sb, x)
 10350:   //sb = fmtBin24 (sb, x)
 10351:   //  24桁2進数変換
 10352:   public static void fmtAin24 (char[] a, int o, int x) {
 10353:     a[o     ] = (char) (x >> 21 & 4 ^ 46);
 10354:     a[o +  1] = (char) (x >> 20 & 4 ^ 46);
 10355:     a[o +  2] = (char) (x >> 19 & 4 ^ 46);
 10356:     a[o +  3] = (char) (x >> 18 & 4 ^ 46);
 10357:     a[o +  4] = (char) (x >> 17 & 4 ^ 46);
 10358:     a[o +  5] = (char) (x >> 16 & 4 ^ 46);
 10359:     a[o +  6] = (char) (x >> 15 & 4 ^ 46);
 10360:     a[o +  7] = (char) (x >> 14 & 4 ^ 46);
 10361:     a[o +  8] = (char) (x >> 13 & 4 ^ 46);
 10362:     a[o +  9] = (char) (x >> 12 & 4 ^ 46);
 10363:     a[o + 10] = (char) (x >> 11 & 4 ^ 46);
 10364:     a[o + 11] = (char) (x >> 10 & 4 ^ 46);
 10365:     a[o + 12] = (char) (x >>  9 & 4 ^ 46);
 10366:     a[o + 13] = (char) (x >>  8 & 4 ^ 46);
 10367:     a[o + 14] = (char) (x >>  7 & 4 ^ 46);
 10368:     a[o + 15] = (char) (x >>  6 & 4 ^ 46);
 10369:     a[o + 16] = (char) (x >>  5 & 4 ^ 46);
 10370:     a[o + 17] = (char) (x >>  4 & 4 ^ 46);
 10371:     a[o + 18] = (char) (x >>  3 & 4 ^ 46);
 10372:     a[o + 19] = (char) (x >>  2 & 4 ^ 46);
 10373:     a[o + 20] = (char) (x >>  1 & 4 ^ 46);
 10374:     a[o + 21] = (char) (x       & 4 ^ 46);
 10375:     a[o + 22] = (char) (x <<  1 & 4 ^ 46);
 10376:     a[o + 23] = (char) (x <<  2 & 4 ^ 46);
 10377:   }  //fmtAin24(char[],int,int)
 10378:   public static void fmtBin24 (char[] a, int o, int x) {
 10379:     a[o     ] = (char) (x >>> 23 & 1 | 48);
 10380:     a[o +  1] = (char) (x >>> 22 & 1 | 48);
 10381:     a[o +  2] = (char) (x >>> 21 & 1 | 48);
 10382:     a[o +  3] = (char) (x >>> 20 & 1 | 48);
 10383:     a[o +  4] = (char) (x >>> 19 & 1 | 48);
 10384:     a[o +  5] = (char) (x >>> 18 & 1 | 48);
 10385:     a[o +  6] = (char) (x >>> 17 & 1 | 48);
 10386:     a[o +  7] = (char) (x >>> 16 & 1 | 48);
 10387:     a[o +  8] = (char) (x >>> 15 & 1 | 48);
 10388:     a[o +  9] = (char) (x >>> 14 & 1 | 48);
 10389:     a[o + 10] = (char) (x >>> 13 & 1 | 48);
 10390:     a[o + 11] = (char) (x >>> 12 & 1 | 48);
 10391:     a[o + 12] = (char) (x >>> 11 & 1 | 48);
 10392:     a[o + 13] = (char) (x >>> 10 & 1 | 48);
 10393:     a[o + 14] = (char) (x >>>  9 & 1 | 48);
 10394:     a[o + 15] = (char) (x >>>  8 & 1 | 48);
 10395:     a[o + 16] = (char) (x >>>  7 & 1 | 48);
 10396:     a[o + 17] = (char) (x >>>  6 & 1 | 48);
 10397:     a[o + 18] = (char) (x >>>  5 & 1 | 48);
 10398:     a[o + 19] = (char) (x >>>  4 & 1 | 48);
 10399:     a[o + 20] = (char) (x >>>  3 & 1 | 48);
 10400:     a[o + 21] = (char) (x >>>  2 & 1 | 48);
 10401:     a[o + 22] = (char) (x >>>  1 & 1 | 48);
 10402:     a[o + 23] = (char) (x        & 1 | 48);
 10403:   }  //fmtBin24(char[],int,int)
 10404:   public static String fmtAin24 (int x) {
 10405:     FMT_TEMP[ 0] = (char) (x >> 21 & 4 ^ 46);
 10406:     FMT_TEMP[ 1] = (char) (x >> 20 & 4 ^ 46);
 10407:     FMT_TEMP[ 2] = (char) (x >> 19 & 4 ^ 46);
 10408:     FMT_TEMP[ 3] = (char) (x >> 18 & 4 ^ 46);
 10409:     FMT_TEMP[ 4] = (char) (x >> 17 & 4 ^ 46);
 10410:     FMT_TEMP[ 5] = (char) (x >> 16 & 4 ^ 46);
 10411:     FMT_TEMP[ 6] = (char) (x >> 15 & 4 ^ 46);
 10412:     FMT_TEMP[ 7] = (char) (x >> 14 & 4 ^ 46);
 10413:     FMT_TEMP[ 8] = (char) (x >> 13 & 4 ^ 46);
 10414:     FMT_TEMP[ 9] = (char) (x >> 12 & 4 ^ 46);
 10415:     FMT_TEMP[10] = (char) (x >> 11 & 4 ^ 46);
 10416:     FMT_TEMP[11] = (char) (x >> 10 & 4 ^ 46);
 10417:     FMT_TEMP[12] = (char) (x >>  9 & 4 ^ 46);
 10418:     FMT_TEMP[13] = (char) (x >>  8 & 4 ^ 46);
 10419:     FMT_TEMP[14] = (char) (x >>  7 & 4 ^ 46);
 10420:     FMT_TEMP[15] = (char) (x >>  6 & 4 ^ 46);
 10421:     FMT_TEMP[16] = (char) (x >>  5 & 4 ^ 46);
 10422:     FMT_TEMP[17] = (char) (x >>  4 & 4 ^ 46);
 10423:     FMT_TEMP[18] = (char) (x >>  3 & 4 ^ 46);
 10424:     FMT_TEMP[19] = (char) (x >>  2 & 4 ^ 46);
 10425:     FMT_TEMP[20] = (char) (x >>  1 & 4 ^ 46);
 10426:     FMT_TEMP[21] = (char) (x       & 4 ^ 46);
 10427:     FMT_TEMP[22] = (char) (x <<  1 & 4 ^ 46);
 10428:     FMT_TEMP[23] = (char) (x <<  2 & 4 ^ 46);
 10429:     return String.valueOf (FMT_TEMP, 0, 24);
 10430:   }  //fmtAin24(int)
 10431:   public static String fmtBin24 (int x) {
 10432:     FMT_TEMP[ 0] = (char) (x >>> 23 & 1 | 48);
 10433:     FMT_TEMP[ 1] = (char) (x >>> 22 & 1 | 48);
 10434:     FMT_TEMP[ 2] = (char) (x >>> 21 & 1 | 48);
 10435:     FMT_TEMP[ 3] = (char) (x >>> 20 & 1 | 48);
 10436:     FMT_TEMP[ 4] = (char) (x >>> 19 & 1 | 48);
 10437:     FMT_TEMP[ 5] = (char) (x >>> 18 & 1 | 48);
 10438:     FMT_TEMP[ 6] = (char) (x >>> 17 & 1 | 48);
 10439:     FMT_TEMP[ 7] = (char) (x >>> 16 & 1 | 48);
 10440:     FMT_TEMP[ 8] = (char) (x >>> 15 & 1 | 48);
 10441:     FMT_TEMP[ 9] = (char) (x >>> 14 & 1 | 48);
 10442:     FMT_TEMP[10] = (char) (x >>> 13 & 1 | 48);
 10443:     FMT_TEMP[11] = (char) (x >>> 12 & 1 | 48);
 10444:     FMT_TEMP[12] = (char) (x >>> 11 & 1 | 48);
 10445:     FMT_TEMP[13] = (char) (x >>> 10 & 1 | 48);
 10446:     FMT_TEMP[14] = (char) (x >>>  9 & 1 | 48);
 10447:     FMT_TEMP[15] = (char) (x >>>  8 & 1 | 48);
 10448:     FMT_TEMP[16] = (char) (x >>>  7 & 1 | 48);
 10449:     FMT_TEMP[17] = (char) (x >>>  6 & 1 | 48);
 10450:     FMT_TEMP[18] = (char) (x >>>  5 & 1 | 48);
 10451:     FMT_TEMP[19] = (char) (x >>>  4 & 1 | 48);
 10452:     FMT_TEMP[20] = (char) (x >>>  3 & 1 | 48);
 10453:     FMT_TEMP[21] = (char) (x >>>  2 & 1 | 48);
 10454:     FMT_TEMP[22] = (char) (x >>>  1 & 1 | 48);
 10455:     FMT_TEMP[23] = (char) (x        & 1 | 48);
 10456:     return String.valueOf (FMT_TEMP, 0, 24);
 10457:   }  //fmtBin24(int)
 10458:   public static StringBuilder fmtAin24 (StringBuilder sb, int x) {
 10459:     FMT_TEMP[ 0] = (char) (x >> 21 & 4 ^ 46);
 10460:     FMT_TEMP[ 1] = (char) (x >> 20 & 4 ^ 46);
 10461:     FMT_TEMP[ 2] = (char) (x >> 19 & 4 ^ 46);
 10462:     FMT_TEMP[ 3] = (char) (x >> 18 & 4 ^ 46);
 10463:     FMT_TEMP[ 4] = (char) (x >> 17 & 4 ^ 46);
 10464:     FMT_TEMP[ 5] = (char) (x >> 16 & 4 ^ 46);
 10465:     FMT_TEMP[ 6] = (char) (x >> 15 & 4 ^ 46);
 10466:     FMT_TEMP[ 7] = (char) (x >> 14 & 4 ^ 46);
 10467:     FMT_TEMP[ 8] = (char) (x >> 13 & 4 ^ 46);
 10468:     FMT_TEMP[ 9] = (char) (x >> 12 & 4 ^ 46);
 10469:     FMT_TEMP[10] = (char) (x >> 11 & 4 ^ 46);
 10470:     FMT_TEMP[11] = (char) (x >> 10 & 4 ^ 46);
 10471:     FMT_TEMP[12] = (char) (x >>  9 & 4 ^ 46);
 10472:     FMT_TEMP[13] = (char) (x >>  8 & 4 ^ 46);
 10473:     FMT_TEMP[14] = (char) (x >>  7 & 4 ^ 46);
 10474:     FMT_TEMP[15] = (char) (x >>  6 & 4 ^ 46);
 10475:     FMT_TEMP[16] = (char) (x >>  5 & 4 ^ 46);
 10476:     FMT_TEMP[17] = (char) (x >>  4 & 4 ^ 46);
 10477:     FMT_TEMP[18] = (char) (x >>  3 & 4 ^ 46);
 10478:     FMT_TEMP[19] = (char) (x >>  2 & 4 ^ 46);
 10479:     FMT_TEMP[20] = (char) (x >>  1 & 4 ^ 46);
 10480:     FMT_TEMP[21] = (char) (x       & 4 ^ 46);
 10481:     FMT_TEMP[22] = (char) (x <<  1 & 4 ^ 46);
 10482:     FMT_TEMP[23] = (char) (x <<  2 & 4 ^ 46);
 10483:     return sb.append (FMT_TEMP, 0, 24);
 10484:   }  //fmtAin24(StringBuilder,int)
 10485:   public static StringBuilder fmtBin24 (StringBuilder sb, int x) {
 10486:     FMT_TEMP[ 0] = (char) (x >>> 23 & 1 | 48);
 10487:     FMT_TEMP[ 1] = (char) (x >>> 22 & 1 | 48);
 10488:     FMT_TEMP[ 2] = (char) (x >>> 21 & 1 | 48);
 10489:     FMT_TEMP[ 3] = (char) (x >>> 20 & 1 | 48);
 10490:     FMT_TEMP[ 4] = (char) (x >>> 19 & 1 | 48);
 10491:     FMT_TEMP[ 5] = (char) (x >>> 18 & 1 | 48);
 10492:     FMT_TEMP[ 6] = (char) (x >>> 17 & 1 | 48);
 10493:     FMT_TEMP[ 7] = (char) (x >>> 16 & 1 | 48);
 10494:     FMT_TEMP[ 8] = (char) (x >>> 15 & 1 | 48);
 10495:     FMT_TEMP[ 9] = (char) (x >>> 14 & 1 | 48);
 10496:     FMT_TEMP[10] = (char) (x >>> 13 & 1 | 48);
 10497:     FMT_TEMP[11] = (char) (x >>> 12 & 1 | 48);
 10498:     FMT_TEMP[12] = (char) (x >>> 11 & 1 | 48);
 10499:     FMT_TEMP[13] = (char) (x >>> 10 & 1 | 48);
 10500:     FMT_TEMP[14] = (char) (x >>>  9 & 1 | 48);
 10501:     FMT_TEMP[15] = (char) (x >>>  8 & 1 | 48);
 10502:     FMT_TEMP[16] = (char) (x >>>  7 & 1 | 48);
 10503:     FMT_TEMP[17] = (char) (x >>>  6 & 1 | 48);
 10504:     FMT_TEMP[18] = (char) (x >>>  5 & 1 | 48);
 10505:     FMT_TEMP[19] = (char) (x >>>  4 & 1 | 48);
 10506:     FMT_TEMP[20] = (char) (x >>>  3 & 1 | 48);
 10507:     FMT_TEMP[21] = (char) (x >>>  2 & 1 | 48);
 10508:     FMT_TEMP[22] = (char) (x >>>  1 & 1 | 48);
 10509:     FMT_TEMP[23] = (char) (x        & 1 | 48);
 10510:     return sb.append (FMT_TEMP, 0, 24);
 10511:   }  //fmtBin24(StringBuilder,int)
 10512: 
 10513:   //--------------------------------------------------------------------------------
 10514:   //16進数変換
 10515:   //
 10516:   //       x               00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f
 10517:   //     9-x               09 08 07 06 05 04 03 02 01 00 ff fe fd fc fb fa
 10518:   //    (9-x)>>4           00 00 00 00 00 00 00 00 00 00 ff ff ff ff ff ff
 10519:   //   ((9-x)>>4)&7        00 00 00 00 00 00 00 00 00 00 07 07 07 07 07 07
 10520:   //  (((9-x)>>4)&7)+48    30 30 30 30 30 30 30 30 30 30 37 37 37 37 37 37
 10521:   //  (((9-x)>>4)&7)+48+x  30 31 32 33 34 35 36 37 38 39 41 42 43 44 45 46
 10522:   //                        0  1  2  3  4  5  6  7  8  9  A  B  C  D  E  F
 10523:   //
 10524:   //       x                00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f
 10525:   //     9-x                09 08 07 06 05 04 03 02 01 00 ff fe fd fc fb fa
 10526:   //    (9-x)>>4            00 00 00 00 00 00 00 00 00 00 ff ff ff ff ff ff
 10527:   //   ((9-x)>>4)&39        00 00 00 00 00 00 00 00 00 00 27 27 27 27 27 27
 10528:   //  (((9-x)>>4)&39)+48    30 30 30 30 30 30 30 30 30 30 57 57 57 57 57 57
 10529:   //  (((9-x)>>4)&39)+48+x  30 31 32 33 34 35 36 37 38 39 61 62 63 64 65 66
 10530:   //                         0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f
 10531:   //
 10532:   //                c               30 31 32 33 34 35 36 37 38 39 41 42 43 44 45 46 61 62 63 64 65 66
 10533:   //             64-c               10 0f 0e 0d 0c 0b 0a 09 08 07 ff fe fd fc fb fa df de dd dc db da
 10534:   //            (64-c)>>8           00 00 00 00 00 00 00 00 00 00 ff ff ff ff ff ff ff ff ff ff ff ff
 10535:   //           ((64-c)>>8)&39       00 00 00 00 00 00 00 00 00 00 27 27 27 27 27 27 27 27 27 27 27 27
 10536:   //          (((64-c)>>8)&39)+48   30 30 30 30 30 30 30 30 30 30 57 57 57 57 57 57 57 57 57 57 57 57
 10537:   //   c|32                         30 31 32 33 34 35 36 37 38 39 61 62 63 64 65 66 61 62 63 64 65 66
 10538:   //  (c|32)-((((64-c)>>8)&39)+48)  00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f 0a 0b 0c 0d 0e 0f
 10539: 
 10540:   //c = fmtHexc (x)
 10541:   //a = fmtHex1 (a, o, x)
 10542:   //s = fmtHex1 (x)
 10543:   //sb = fmtHex1 (sb, x)
 10544:   //  1桁16進数変換
 10545:   public static char fmtHexc (int x) {
 10546:     x &= 15;
 10547:     return (char) ((((9 - x) >> 4) & 7) + 48 + x);
 10548:   }  //fmtHexc(int)
 10549:   public static void fmtHex1 (char[] a, int o, int x) {
 10550:     x &= 15;
 10551:     a[o] = (char) ((((9 - x) >> 4) & 7) + 48 + x);
 10552:   }  //fmtHex1(char[],int,int)
 10553:   public static String fmtHex1 (int x) {
 10554:     x &= 15;
 10555:     return Character.toString ((char) ((((9 - x) >> 4) & 7) + 48 + x));
 10556:   }  //fmtHex1(int)
 10557:   public static StringBuilder fmtHex1 (StringBuilder sb, int x) {
 10558:     x &= 15;
 10559:     return sb.append ((char) ((((9 - x) >> 4) & 7) + 48 + x));
 10560:   }  //fmtHex1(StringBuilder,int)
 10561: 
 10562:   //fmtHex2 (a, o, x)
 10563:   //s = fmtHex2 (x)
 10564:   //sb = fmtHex2 (sb, x)
 10565:   //  2桁16進数変換
 10566:   //  byte用
 10567:   public static void fmtHex2 (char[] a, int o, int x) {
 10568:     int x0 = x        & 15;
 10569:     int x1 = x >>>  4 & 15;
 10570:     a[o    ] = (char) ((((9 - x1) >> 4) & 7) + 48 + x1);
 10571:     a[o + 1] = (char) ((((9 - x0) >> 4) & 7) + 48 + x0);
 10572:   }  //fmtHex2(char[],int,int)
 10573:   public static String fmtHex2 (int x) {
 10574:     //fmtHex2 (FMT_TEMP, 0, x);
 10575:     int x0 = x        & 15;
 10576:     int x1 = x >>>  4 & 15;
 10577:     FMT_TEMP[0] = (char) ((((9 - x1) >> 4) & 7) + 48 + x1);
 10578:     FMT_TEMP[1] = (char) ((((9 - x0) >> 4) & 7) + 48 + x0);
 10579:     return String.valueOf (FMT_TEMP, 0, 2);
 10580:   }  //fmtHex2(int)
 10581:   public static StringBuilder fmtHex2 (StringBuilder sb, int x) {
 10582:     int x0 = x        & 15;
 10583:     int x1 = x >>>  4 & 15;
 10584:     return (sb.
 10585:             append ((char) ((((9 - x1) >> 4) & 7) + 48 + x1)).
 10586:             append ((char) ((((9 - x0) >> 4) & 7) + 48 + x0)));
 10587:   }  //fmtHex2(StringBuilder,int)
 10588: 
 10589:   //fmtHex4 (a, o, x)
 10590:   //s = fmtHex4 (x)
 10591:   //sb = fmtHex4 (sb, x)
 10592:   //  4桁16進数変換
 10593:   //  word用
 10594:   public static void fmtHex4 (char[] a, int o, int x) {
 10595:     int t;
 10596:     t = (char) x >>> 12;
 10597:     a[o    ] = (char) ((((9 - t) >> 4) & 7) + 48 + t);
 10598:     t =        x >>>  8 & 15;
 10599:     a[o + 1] = (char) ((((9 - t) >> 4) & 7) + 48 + t);
 10600:     t =        x >>>  4 & 15;
 10601:     a[o + 2] = (char) ((((9 - t) >> 4) & 7) + 48 + t);
 10602:     t =        x        & 15;
 10603:     a[o + 3] = (char) ((((9 - t) >> 4) & 7) + 48 + t);
 10604:   }  //fmtHex4(char[],int,int)
 10605:   public static String fmtHex4 (int x) {
 10606:     //fmtHex4 (FMT_TEMP, 0, x);
 10607:     int t;
 10608:     t = (char) x >>> 12;
 10609:     FMT_TEMP[0] = (char) ((((9 - t) >> 4) & 7) + 48 + t);
 10610:     t =        x >>>  8 & 15;
 10611:     FMT_TEMP[1] = (char) ((((9 - t) >> 4) & 7) + 48 + t);
 10612:     t =        x >>>  4 & 15;
 10613:     FMT_TEMP[2] = (char) ((((9 - t) >> 4) & 7) + 48 + t);
 10614:     t =        x        & 15;
 10615:     FMT_TEMP[3] = (char) ((((9 - t) >> 4) & 7) + 48 + t);
 10616:     return String.valueOf (FMT_TEMP, 0, 4);
 10617:   }  //fmtHex4(int)
 10618:   public static StringBuilder fmtHex4 (StringBuilder sb, int x) {
 10619:     //fmtHex4 (FMT_TEMP, 0, x);
 10620:     int t;
 10621:     t = (char) x >>> 12;
 10622:     FMT_TEMP[0] = (char) ((((9 - t) >> 4) & 7) + 48 + t);
 10623:     t =        x >>>  8 & 15;
 10624:     FMT_TEMP[1] = (char) ((((9 - t) >> 4) & 7) + 48 + t);
 10625:     t =        x >>>  4 & 15;
 10626:     FMT_TEMP[2] = (char) ((((9 - t) >> 4) & 7) + 48 + t);
 10627:     t =        x        & 15;
 10628:     FMT_TEMP[3] = (char) ((((9 - t) >> 4) & 7) + 48 + t);
 10629:     return sb.append (FMT_TEMP, 0, 4);
 10630:   }  //fmtHex4(StringBuilder,int)
 10631: 
 10632:   //fmtHex6 (a, o, x)
 10633:   //s = fmtHex6 (x)
 10634:   //sb = fmtHex6 (sb, x)
 10635:   //  6桁16進数変換
 10636:   //  rgb用
 10637:   public static void fmtHex6 (char[] a, int o, int x) {
 10638:     int t;
 10639:     t =        x >>> 20 & 15;
 10640:     a[o    ] = (char) ((((9 - t) >> 4) & 7) + 48 + t);
 10641:     t =        x >>> 16 & 15;
 10642:     a[o + 1] = (char) ((((9 - t) >> 4) & 7) + 48 + t);
 10643:     t = (char) x >>> 12;
 10644:     a[o + 2] = (char) ((((9 - t) >> 4) & 7) + 48 + t);
 10645:     t =        x >>>  8 & 15;
 10646:     a[o + 3] = (char) ((((9 - t) >> 4) & 7) + 48 + t);
 10647:     t =        x >>>  4 & 15;
 10648:     a[o + 4] = (char) ((((9 - t) >> 4) & 7) + 48 + t);
 10649:     t =        x        & 15;
 10650:     a[o + 5] = (char) ((((9 - t) >> 4) & 7) + 48 + t);
 10651:   }  //fmtHex6(char[],int,int)
 10652:   public static String fmtHex6 (int x) {
 10653:     //fmtHex6 (FMT_TEMP, 0, x);
 10654:     int t;
 10655:     t =        x >>> 20 & 15;
 10656:     FMT_TEMP[0] = (char) ((((9 - t) >> 4) & 7) + 48 + t);
 10657:     t =        x >>> 16 & 15;
 10658:     FMT_TEMP[1] = (char) ((((9 - t) >> 4) & 7) + 48 + t);
 10659:     t = (char) x >>> 12;
 10660:     FMT_TEMP[2] = (char) ((((9 - t) >> 4) & 7) + 48 + t);
 10661:     t =        x >>>  8 & 15;
 10662:     FMT_TEMP[3] = (char) ((((9 - t) >> 4) & 7) + 48 + t);
 10663:     t =        x >>>  4 & 15;
 10664:     FMT_TEMP[4] = (char) ((((9 - t) >> 4) & 7) + 48 + t);
 10665:     t =        x        & 15;
 10666:     FMT_TEMP[5] = (char) ((((9 - t) >> 4) & 7) + 48 + t);
 10667:     return String.valueOf (FMT_TEMP, 0, 6);
 10668:   }  //fmtHex6(int)
 10669:   public static StringBuilder fmtHex6 (StringBuilder sb, int x) {
 10670:     //fmtHex6 (FMT_TEMP, 0, x);
 10671:     int t;
 10672:     t =        x >>> 20 & 15;
 10673:     FMT_TEMP[0] = (char) ((((9 - t) >> 4) & 7) + 48 + t);
 10674:     t =        x >>> 16 & 15;
 10675:     FMT_TEMP[1] = (char) ((((9 - t) >> 4) & 7) + 48 + t);
 10676:     t = (char) x >>> 12;
 10677:     FMT_TEMP[2] = (char) ((((9 - t) >> 4) & 7) + 48 + t);
 10678:     t =        x >>>  8 & 15;
 10679:     FMT_TEMP[3] = (char) ((((9 - t) >> 4) & 7) + 48 + t);
 10680:     t =        x >>>  4 & 15;
 10681:     FMT_TEMP[4] = (char) ((((9 - t) >> 4) & 7) + 48 + t);
 10682:     t =        x        & 15;
 10683:     FMT_TEMP[5] = (char) ((((9 - t) >> 4) & 7) + 48 + t);
 10684:     return sb.append (FMT_TEMP, 0, 6);
 10685:   }  //fmtHex6(StringBuilder,int)
 10686: 
 10687:   //fmtHex8 (a, o, x)
 10688:   //s = fmtHex8 (x)
 10689:   //sb = fmtHex8 (sb, x)
 10690:   //  8桁16進数変換
 10691:   //  argb,long用
 10692:   public static void fmtHex8 (char[] a, int o, int x) {
 10693:     int t;
 10694:     t =        x >>> 28;
 10695:     a[o    ] = (char) ((((9 - t) >> 4) & 7) + 48 + t);
 10696:     t =        x >>> 24 & 15;
 10697:     a[o + 1] = (char) ((((9 - t) >> 4) & 7) + 48 + t);
 10698:     t =        x >>> 20 & 15;
 10699:     a[o + 2] = (char) ((((9 - t) >> 4) & 7) + 48 + t);
 10700:     t =        x >>> 16 & 15;
 10701:     a[o + 3] = (char) ((((9 - t) >> 4) & 7) + 48 + t);
 10702:     t = (char) x >>> 12;
 10703:     a[o + 4] = (char) ((((9 - t) >> 4) & 7) + 48 + t);
 10704:     t =        x >>>  8 & 15;
 10705:     a[o + 5] = (char) ((((9 - t) >> 4) & 7) + 48 + t);
 10706:     t =        x >>>  4 & 15;
 10707:     a[o + 6] = (char) ((((9 - t) >> 4) & 7) + 48 + t);
 10708:     t =        x        & 15;
 10709:     a[o + 7] = (char) ((((9 - t) >> 4) & 7) + 48 + t);
 10710:   }  //fmtHex8(char[],int,int)
 10711:   public static String fmtHex8 (int x) {
 10712:     //fmtHex8 (FMT_TEMP, 0, x);
 10713:     int t;
 10714:     t =        x >>> 28;
 10715:     FMT_TEMP[0] = (char) ((((9 - t) >> 4) & 7) + 48 + t);
 10716:     t =        x >>> 24 & 15;
 10717:     FMT_TEMP[1] = (char) ((((9 - t) >> 4) & 7) + 48 + t);
 10718:     t =        x >>> 20 & 15;
 10719:     FMT_TEMP[2] = (char) ((((9 - t) >> 4) & 7) + 48 + t);
 10720:     t =        x >>> 16 & 15;
 10721:     FMT_TEMP[3] = (char) ((((9 - t) >> 4) & 7) + 48 + t);
 10722:     t = (char) x >>> 12;
 10723:     FMT_TEMP[4] = (char) ((((9 - t) >> 4) & 7) + 48 + t);
 10724:     t =        x >>>  8 & 15;
 10725:     FMT_TEMP[5] = (char) ((((9 - t) >> 4) & 7) + 48 + t);
 10726:     t =        x >>>  4 & 15;
 10727:     FMT_TEMP[6] = (char) ((((9 - t) >> 4) & 7) + 48 + t);
 10728:     t =        x        & 15;
 10729:     FMT_TEMP[7] = (char) ((((9 - t) >> 4) & 7) + 48 + t);
 10730:     return String.valueOf (FMT_TEMP, 0, 8);
 10731:   }  //fmtHex8(int)
 10732:   public static StringBuilder fmtHex8 (StringBuilder sb, int x) {
 10733:     //fmtHex8 (FMT_TEMP, 0, x);
 10734:     int t;
 10735:     t =        x >>> 28;
 10736:     FMT_TEMP[0] = (char) ((((9 - t) >> 4) & 7) + 48 + t);
 10737:     t =        x >>> 24 & 15;
 10738:     FMT_TEMP[1] = (char) ((((9 - t) >> 4) & 7) + 48 + t);
 10739:     t =        x >>> 20 & 15;
 10740:     FMT_TEMP[2] = (char) ((((9 - t) >> 4) & 7) + 48 + t);
 10741:     t =        x >>> 16 & 15;
 10742:     FMT_TEMP[3] = (char) ((((9 - t) >> 4) & 7) + 48 + t);
 10743:     t = (char) x >>> 12;
 10744:     FMT_TEMP[4] = (char) ((((9 - t) >> 4) & 7) + 48 + t);
 10745:     t =        x >>>  8 & 15;
 10746:     FMT_TEMP[5] = (char) ((((9 - t) >> 4) & 7) + 48 + t);
 10747:     t =        x >>>  4 & 15;
 10748:     FMT_TEMP[6] = (char) ((((9 - t) >> 4) & 7) + 48 + t);
 10749:     t =        x        & 15;
 10750:     FMT_TEMP[7] = (char) ((((9 - t) >> 4) & 7) + 48 + t);
 10751:     return sb.append (FMT_TEMP, 0, 8);
 10752:   }  //fmtHex8(StringBuilder,int)
 10753: 
 10754:   public static StringBuilder fmtHex16 (StringBuilder sb, long x) {
 10755:     //fmtHex16 (FMT_TEMP, 0, x);
 10756:     int s, t;
 10757:     s = (int) (x >>> 32);
 10758:     t =        s >>> 28;
 10759:     FMT_TEMP[ 0] = (char) ((((9 - t) >> 4) & 7) + 48 + t);
 10760:     t =        s >>> 24 & 15;
 10761:     FMT_TEMP[ 1] = (char) ((((9 - t) >> 4) & 7) + 48 + t);
 10762:     t =        s >>> 20 & 15;
 10763:     FMT_TEMP[ 2] = (char) ((((9 - t) >> 4) & 7) + 48 + t);
 10764:     t =        s >>> 16 & 15;
 10765:     FMT_TEMP[ 3] = (char) ((((9 - t) >> 4) & 7) + 48 + t);
 10766:     t = (char) s >>> 12;
 10767:     FMT_TEMP[ 4] = (char) ((((9 - t) >> 4) & 7) + 48 + t);
 10768:     t =        s >>>  8 & 15;
 10769:     FMT_TEMP[ 5] = (char) ((((9 - t) >> 4) & 7) + 48 + t);
 10770:     t =        s >>>  4 & 15;
 10771:     FMT_TEMP[ 6] = (char) ((((9 - t) >> 4) & 7) + 48 + t);
 10772:     t =        s        & 15;
 10773:     FMT_TEMP[ 7] = (char) ((((9 - t) >> 4) & 7) + 48 + t);
 10774:     s = (int)  x;
 10775:     t =        s >>> 28;
 10776:     FMT_TEMP[ 8] = (char) ((((9 - t) >> 4) & 7) + 48 + t);
 10777:     t =        s >>> 24 & 15;
 10778:     FMT_TEMP[ 9] = (char) ((((9 - t) >> 4) & 7) + 48 + t);
 10779:     t =        s >>> 20 & 15;
 10780:     FMT_TEMP[10] = (char) ((((9 - t) >> 4) & 7) + 48 + t);
 10781:     t =        s >>> 16 & 15;
 10782:     FMT_TEMP[11] = (char) ((((9 - t) >> 4) & 7) + 48 + t);
 10783:     t = (char) s >>> 12;
 10784:     FMT_TEMP[12] = (char) ((((9 - t) >> 4) & 7) + 48 + t);
 10785:     t =        s >>>  8 & 15;
 10786:     FMT_TEMP[13] = (char) ((((9 - t) >> 4) & 7) + 48 + t);
 10787:     t =        s >>>  4 & 15;
 10788:     FMT_TEMP[14] = (char) ((((9 - t) >> 4) & 7) + 48 + t);
 10789:     t =        s        & 15;
 10790:     FMT_TEMP[15] = (char) ((((9 - t) >> 4) & 7) + 48 + t);
 10791:     return sb.append (FMT_TEMP, 0, 16);
 10792:   }  //fmtHex16(StringBuilder,long)
 10793: 
 10794:   //--------------------------------------------------------------------------------
 10795:   //10進数変換
 10796:   //  除算は遅いので逆数乗算で商と余りを求めて下位から充填する
 10797:   //  x/yを計算する代わりにceil(pow(2,n)/y)を掛けてから右にnビットシフトする
 10798:   //  m=((1<<n)+y-1)/yとおくと0<=x<=((((m-1)/(m*y-(1<<n))+1)<<n)-1)/mの範囲でx/yはm*x>>nに置き換えられる
 10799:   //    >perl -e "use GMP::Mpz qw(:all);$y=mpz(10);for($n=mpz(0);$n<=31;$n++){$m=((1<<$n)+$y-1)/$y;$l=(((($m-1)/($m*$y-(1<<$n))+1)<<$n)-1)/$m;printf'x*%s>>%s (0<=x<=%s)%c',$m,$n,$l,10;}"
 10800:   //    x*1>>0 (0<=x<=0)
 10801:   //    x*1>>1 (0<=x<=1)
 10802:   //    x*1>>2 (0<=x<=3)
 10803:   //    x*1>>3 (0<=x<=7)
 10804:   //    x*2>>4 (0<=x<=7)
 10805:   //    x*4>>5 (0<=x<=7)
 10806:   //    x*7>>6 (0<=x<=18)
 10807:   //    x*13>>7 (0<=x<=68)
 10808:   //    x*26>>8 (0<=x<=68)
 10809:   //    x*52>>9 (0<=x<=68)
 10810:   //    x*103>>10 (0<=x<=178)  2桁
 10811:   //    x*205>>11 (0<=x<=1028)  3桁
 10812:   //    x*410>>12 (0<=x<=1028)
 10813:   //    x*820>>13 (0<=x<=1028)
 10814:   //    x*1639>>14 (0<=x<=2738)
 10815:   //    x*3277>>15 (0<=x<=16388)  4桁
 10816:   //    x*6554>>16 (0<=x<=16388)
 10817:   //    x*13108>>17 (0<=x<=16388)
 10818:   //    x*26215>>18 (0<=x<=43698)
 10819:   //    x*52429>>19 (0<=x<=262148)  5桁。ここからlong
 10820:   //    x*104858>>20 (0<=x<=262148)
 10821:   //    x*209716>>21 (0<=x<=262148)
 10822:   //    x*419431>>22 (0<=x<=699058)
 10823:   //    x*838861>>23 (0<=x<=4194308)  6桁
 10824:   //    x*1677722>>24 (0<=x<=4194308)
 10825:   //    x*3355444>>25 (0<=x<=4194308)
 10826:   //    x*6710887>>26 (0<=x<=11184818)  7桁
 10827:   //    x*13421773>>27 (0<=x<=67108868)
 10828:   //    x*26843546>>28 (0<=x<=67108868)
 10829:   //    x*53687092>>29 (0<=x<=67108868)
 10830:   //    x*107374183>>30 (0<=x<=178956978)  8桁
 10831:   //    x*214748365>>31 (0<=x<=1073741828)  9桁
 10832:   //
 10833:   //  検算
 10834:   //    >perl -e "use GMP::Mpz qw(:all);$y=mpz(10);for($n=mpz(0);$n<=23;$n++){$m=((1<<$n)+$y-1)/$y;$l=(((($m-1)/($m*$y-(1<<$n))+1)<<$n)-1)/$m;for($x=mpz(0);$x<=$l+1;$x++){$t=$m*$x>>$n;$z=$x/$y;if($z!=$t){printf'n=%d,m=%d,l=%d,x=%d,y=%d,z=%d,t=%d%c',$n,$m,$l,$x,$y,$z,$t,10;}}}"
 10835:   //    n=0,m=1,l=0,x=1,y=10,z=0,t=1
 10836:   //    n=1,m=1,l=1,x=2,y=10,z=0,t=1
 10837:   //    n=2,m=1,l=3,x=4,y=10,z=0,t=1
 10838:   //    n=3,m=1,l=7,x=8,y=10,z=0,t=1
 10839:   //    n=4,m=2,l=7,x=8,y=10,z=0,t=1
 10840:   //    n=5,m=4,l=7,x=8,y=10,z=0,t=1
 10841:   //    n=6,m=7,l=18,x=19,y=10,z=1,t=2
 10842:   //    n=7,m=13,l=68,x=69,y=10,z=6,t=7
 10843:   //    n=8,m=26,l=68,x=69,y=10,z=6,t=7
 10844:   //    n=9,m=52,l=68,x=69,y=10,z=6,t=7
 10845:   //    n=10,m=103,l=178,x=179,y=10,z=17,t=18
 10846:   //    n=11,m=205,l=1028,x=1029,y=10,z=102,t=103
 10847:   //    n=12,m=410,l=1028,x=1029,y=10,z=102,t=103
 10848:   //    n=13,m=820,l=1028,x=1029,y=10,z=102,t=103
 10849:   //    n=14,m=1639,l=2738,x=2739,y=10,z=273,t=274
 10850:   //    n=15,m=3277,l=16388,x=16389,y=10,z=1638,t=1639
 10851:   //    n=16,m=6554,l=16388,x=16389,y=10,z=1638,t=1639
 10852:   //    n=17,m=13108,l=16388,x=16389,y=10,z=1638,t=1639
 10853:   //    n=18,m=26215,l=43698,x=43699,y=10,z=4369,t=4370
 10854:   //    n=19,m=52429,l=262148,x=262149,y=10,z=26214,t=26215
 10855:   //    n=20,m=104858,l=262148,x=262149,y=10,z=26214,t=26215
 10856:   //    n=21,m=209716,l=262148,x=262149,y=10,z=26214,t=26215
 10857:   //    n=22,m=419431,l=699058,x=699059,y=10,z=69905,t=69906
 10858:   //    n=23,m=838861,l=4194308,x=4194309,y=10,z=419430,t=419431
 10859: 
 10860:   //  4桁まではあらかじめテーブルに展開しておく
 10861:   public static final int[] FMT_BCD4 = new int[10000];
 10862:   public static final int[] FMT_DCB4 = new int[65536];
 10863: 
 10864:   //--------------------------------------------------------------------------------
 10865:   //fmtInit ()
 10866:   //  初期化
 10867:   public static void fmtInit () {
 10868:     Arrays.fill (FMT_DCB4, -1);
 10869:     int i = 0;
 10870:     int x = 0;
 10871:     for (int a = 0; a < 10; a++) {
 10872:       for (int b = 0; b < 10; b++) {
 10873:         for (int c = 0; c < 10; c++) {
 10874:           FMT_DCB4[FMT_BCD4[i    ] = x    ] = i;
 10875:           FMT_DCB4[FMT_BCD4[i + 1] = x + 1] = i + 1;
 10876:           FMT_DCB4[FMT_BCD4[i + 2] = x + 2] = i + 2;
 10877:           FMT_DCB4[FMT_BCD4[i + 3] = x + 3] = i + 3;
 10878:           FMT_DCB4[FMT_BCD4[i + 4] = x + 4] = i + 4;
 10879:           FMT_DCB4[FMT_BCD4[i + 5] = x + 5] = i + 5;
 10880:           FMT_DCB4[FMT_BCD4[i + 6] = x + 6] = i + 6;
 10881:           FMT_DCB4[FMT_BCD4[i + 7] = x + 7] = i + 7;
 10882:           FMT_DCB4[FMT_BCD4[i + 8] = x + 8] = i + 8;
 10883:           FMT_DCB4[FMT_BCD4[i + 9] = x + 9] = i + 9;
 10884:           i += 10;
 10885:           x += 1 << 4;
 10886:         }
 10887:         x += 6 << 4;
 10888:       }
 10889:       x += 6 << 8;
 10890:     }
 10891:   }  //fmtInit()
 10892: 
 10893:   //y = fmtBcd4 (x)
 10894:   //  xを0~9999にクリッピングしてから4桁のBCDに変換する
 10895:   public static int fmtBcd4 (int x) {
 10896:     //x = Math.max (0, Math.min (9999, x));
 10897:     //perl optdiv.pl 9999 10
 10898:     //  x/10==x*3277>>>15 (0<=x<=16388) [9999*3277==32766723]
 10899:     //int t = x * 3277 >> 15;  //x/10
 10900:     //int y = x - t * 10;  //1の位
 10901:     //x = t * 3277 >> 15;  //x/100
 10902:     //y |= t - x * 10 << 4;  //10の位
 10903:     //t = x * 3277 >> 15;  //x/1000
 10904:     //return t << 12 | x - t * 10 << 8 | y;  //1000の位,100の位
 10905:     return FMT_BCD4[Math.max (0, Math.min (9999, x))];
 10906:   }  //fmtBcd4(int)
 10907: 
 10908:   //y = fmtBcd8 (x)
 10909:   //  xを0~99999999にクリッピングしてから8桁のBCDに変換する
 10910:   public static int fmtBcd8 (int x) {
 10911:     x = Math.max (0, Math.min (99999999, x));
 10912:     //perl optdiv.pl 99999999 10000
 10913:     //  x/10000==x*109951163>>>40 (0<=x<=494389998) [99999999*109951163==10995116190048837]
 10914:     int q = (int) ((long) x * 109951163L >>> 40);  //x/10000。1.6ns@2000000000
 10915:     //int q = x / 10000;  //2.0ns@2000000000
 10916:     return FMT_BCD4[q] << 16 | FMT_BCD4[x - 10000 * q];
 10917:   }  //fmtBcd8(int)
 10918: 
 10919:   //y = fmtBcd12 (x)
 10920:   //  xを0~999999999999Lにクリッピングしてから12桁のBCDに変換する
 10921:   public static long fmtBcd12 (long x) {
 10922:     x = Math.max (0L, Math.min (999999999999L, x));
 10923:     int q = (int) ((double) x / 100000000.0);  //(int) (x / 100000000L);
 10924:     int r = (int) (x - 100000000L * q);
 10925:     //perl optdiv.pl 99999999 10000
 10926:     //  x/10000==x*109951163>>>40 (0<=x<=494389998) [99999999*109951163==10995116190048837]
 10927:     int rq = (int) ((long) r * 109951163L >>> 40);  //r/10000
 10928:     //int rq = r / 10000;
 10929:     return (long) FMT_BCD4[q] << 32 | 0xffffffffL & (FMT_BCD4[rq] << 16 | FMT_BCD4[r - 10000 * rq]);
 10930:   }  //fmtBcd12(long)
 10931: 
 10932:   //y = fmtBcd16 (x)
 10933:   //  xを0~9999999999999999Lにクリッピングしてから16桁のBCDに変換する
 10934:   public static long fmtBcd16 (long x) {
 10935:     x = Math.max (0L, Math.min (9999999999999999L, x));
 10936:     int q = x <= (1L << 53) ? (int) ((double) x / 100000000.0) : (int) (x / 100000000L);
 10937:     int r = (int) (x - 100000000L * q);
 10938:     //perl optdiv.pl 99999999 10000
 10939:     //  x/10000==x*109951163>>>40 (0<=x<=494389998) [99999999*109951163==10995116190048837]
 10940:     int qq = (int) ((long) q * 109951163L >>> 40);  //q/10000
 10941:     //int qq = q / 10000;
 10942:     //perl optdiv.pl 99999999 10000
 10943:     //  x/10000==x*109951163>>>40 (0<=x<=494389998) [99999999*109951163==10995116190048837]
 10944:     int rq = (int) ((long) r * 109951163L >>> 40);  //r/10000
 10945:     //int rq = r / 10000;
 10946:     return (long) (FMT_BCD4[qq] << 16 | FMT_BCD4[q - 10000 * qq]) << 32 | 0xffffffffL & (FMT_BCD4[rq] << 16 | FMT_BCD4[r - 10000 * rq]);
 10947:   }  //fmtBcd16(long)
 10948: 
 10949:   //--------------------------------------------------------------------------------
 10950:   //o = fmtCA02u (a, o, x)
 10951:   //sb = fmtSB02u (sb, x)
 10952:   //  %02u
 10953:   //  2桁10進数変換(符号なし,ゼロサプレスなし)
 10954:   public static int fmtCA02u (char[] a, int o, int x) {
 10955:     if (x < 0 || 99 < x) {
 10956:       x = 99;
 10957:     }
 10958:     x = FMT_BCD4[x];
 10959:     a[o    ] = (char) ('0' | x >>> 4);
 10960:     a[o + 1] = (char) ('0' | x        & 15);
 10961:     return o + 2;
 10962:   }  //fmtCA02u(char[],int,int)
 10963:   public static StringBuilder fmtSB02u (StringBuilder sb, int x) {
 10964:     return sb.append (FMT_TEMP, 0, fmtCA02u (FMT_TEMP, 0, x));
 10965:   }  //fmtSB02u(StringBuilder,int)
 10966: 
 10967:   //o = fmtCA2u (a, o, x)
 10968:   //sb = fmtSB2u (sb, x)
 10969:   //  %2u
 10970:   //  2桁10進数変換(符号なし,ゼロサプレスあり)
 10971:   public static int fmtCA2u (char[] a, int o, int x) {
 10972:     if (x < 0 || 99 < x) {
 10973:       x = 99;
 10974:     }
 10975:     x = FMT_BCD4[x];
 10976:     if (x <= 0x000f) {  //1桁
 10977:       a[o++] = (char) ('0' | x);
 10978:     } else {  //2桁
 10979:       a[o++] = (char) ('0' | x >>>  4);
 10980:       a[o++] = (char) ('0' | x        & 15);
 10981:     }
 10982:     return o;
 10983:   }  //fmtCA2u(char[],int,int)
 10984:   public static StringBuilder fmtSB2u (StringBuilder sb, int x) {
 10985:     return sb.append (FMT_TEMP, 0, fmtCA2u (FMT_TEMP, 0, x));
 10986:   }  //fmtSB2u(StringBuilder,int)
 10987: 
 10988:   //o = fmtCA04u (a, o, x)
 10989:   //sb = fmtSB04u (sb, x)
 10990:   //  %04u
 10991:   //  4桁10進数変換(符号なし,ゼロサプレスなし)
 10992:   public static int fmtCA04u (char[] a, int o, int x) {
 10993:     if (x < 0 || 9999 < x) {
 10994:       x = 9999;
 10995:     }
 10996:     x = FMT_BCD4[x];
 10997:     a[o    ] = (char) ('0' | x >>> 12);
 10998:     a[o + 1] = (char) ('0' | x >>>  8 & 15);
 10999:     a[o + 2] = (char) ('0' | x >>>  4 & 15);
 11000:     a[o + 3] = (char) ('0' | x        & 15);
 11001:     return o + 4;
 11002:   }  //fmtCA04u(char[],int,int)
 11003:   public static StringBuilder fmtSB04u (StringBuilder sb, int x) {
 11004:     return sb.append (FMT_TEMP, 0, fmtCA04u (FMT_TEMP, 0, x));
 11005:   }  //fmtSB04u(StringBuilder,int)
 11006: 
 11007:   //o = fmtCA4u (a, o, x)
 11008:   //sb = fmtSB4u (sb, x)
 11009:   //  %4u
 11010:   //  4桁10進数変換(符号なし,ゼロサプレスあり)
 11011:   public static int fmtCA4u (char[] a, int o, int x) {
 11012:     if (x < 0 || 9999 < x) {
 11013:       x = 9999;
 11014:     }
 11015:     x = FMT_BCD4[x];
 11016:     if (x <= 0x000f) {  //1桁
 11017:       a[o++] = (char) ('0' | x);
 11018:     } else if (x <= 0x00ff) {  //2桁
 11019:       a[o++] = (char) ('0' | x >>>  4);
 11020:       a[o++] = (char) ('0' | x        & 15);
 11021:     } else if (x <= 0x0fff) {  //3桁
 11022:       a[o++] = (char) ('0' | x >>>  8);
 11023:       a[o++] = (char) ('0' | x >>>  4 & 15);
 11024:       a[o++] = (char) ('0' | x        & 15);
 11025:     } else {  //4桁
 11026:       a[o++] = (char) ('0' | x >>> 12);
 11027:       a[o++] = (char) ('0' | x >>>  8 & 15);
 11028:       a[o++] = (char) ('0' | x >>>  4 & 15);
 11029:       a[o++] = (char) ('0' | x        & 15);
 11030:     }
 11031:     return o;
 11032:   }  //fmtCA4u(char[],int,int)
 11033:   public static StringBuilder fmtSB4u (StringBuilder sb, int x) {
 11034:     return sb.append (FMT_TEMP, 0, fmtCA4u (FMT_TEMP, 0, x));
 11035:   }  //fmtSB4u(StringBuilder,int)
 11036: 
 11037:   //o = fmtCA08u (a, o, x)
 11038:   //sb = fmtSB08u (sb, x)
 11039:   //  %08u
 11040:   //  8桁10進数変換(符号なし,ゼロサプレスなし)
 11041:   public static int fmtCA08u (char[] a, int o, int x) {
 11042:     if (x < 0 || 99999999 < x) {
 11043:       x = 99999999;
 11044:     }
 11045:     //perl optdiv.pl 99999999 10000
 11046:     //  x/10000==x*109951163>>>40 (0<=x<=494389998) [99999999*109951163==10995116190048837]
 11047:     int h = (int) ((long) x * 109951163L >>> 40);  //x/10000
 11048:     return fmtCA04u (a, fmtCA04u (a, o, h), x - h * 10000);
 11049:   }  //fmtCA08u(char[],int,int)
 11050:   public static StringBuilder fmtSB08u (StringBuilder sb, int x) {
 11051:     return sb.append (FMT_TEMP, 0, fmtCA08u (FMT_TEMP, 0, x));
 11052:   }  //fmtSB08u(StringBuilder,int)
 11053: 
 11054:   //o = fmtCA8u (a, o, x)
 11055:   //sb = fmtSB8u (sb, x)
 11056:   //  %8u
 11057:   //  8桁10進数変換(符号なし,ゼロサプレスあり)
 11058:   public static int fmtCA8u (char[] a, int o, int x) {
 11059:     if (x < 0 || 99999999 < x) {
 11060:       x = 99999999;
 11061:     }
 11062:     if (x <= 9999) {  //1~4桁
 11063:       return fmtCA4u (a, o, x);
 11064:     } else {  //5~8桁
 11065:       //perl optdiv.pl 99999999 10000
 11066:       //  x/10000==x*109951163>>>40 (0<=x<=494389998) [99999999*109951163==10995116190048837]
 11067:       int h = (int) ((long) x * 109951163L >>> 40);  //x/10000
 11068:       return fmtCA04u (a, fmtCA4u (a, o, h), x - h * 10000);
 11069:     }
 11070:   }  //fmtCA8u(char[],int,int)
 11071:   public static StringBuilder fmtSB8u (StringBuilder sb, int x) {
 11072:     return sb.append (FMT_TEMP, 0, fmtCA8u (FMT_TEMP, 0, x));
 11073:   }  //fmtSB8u(StringBuilder,int)
 11074: 
 11075:   //o = fmtCAd (a, o, x)
 11076:   //sb = fmtSBd (sb, x)
 11077:   //  %d
 11078:   //  10進数変換(符号あり,ゼロサプレスあり)
 11079:   public static int fmtCAd (char[] a, int o, long x) {
 11080:     if (x < 0L) {
 11081:       x = -x;
 11082:       a[o++] = '-';
 11083:     }
 11084:     if (x <= 99999999L) {  //1~8桁
 11085:       return fmtCA8u (a, o, (int) x);
 11086:     } else if (x <= 9999999999999999L) {  //9~16桁
 11087:       long h = x / 100000000L;
 11088:       return fmtCA08u (a, fmtCA8u (a, o, (int) h), (int) (x - h * 100000000L));
 11089:     } else {  //17~19桁
 11090:       long hh = x / 10000000000000000L;
 11091:       x -= hh * 10000000000000000L;
 11092:       long h = x / 100000000L;
 11093:       return fmtCA08u (a, fmtCA08u (a, fmtCA4u (a, o, (int) hh), (int) h), (int) (x - h * 100000000L));
 11094:     }
 11095:   }  //fmtCAd(char[],int,long)
 11096:   public static StringBuilder fmtSBd (StringBuilder sb, long x) {
 11097:     return sb.append (FMT_TEMP, 0, fmtCAd (FMT_TEMP, 0, x));
 11098:   }  //fmtSBd(StringBuilder,long)
 11099: 
 11100:   //o = fmtCAnd (a, o, n, x)
 11101:   //sb = fmtSBnd (sb, n, x)
 11102:   //  %*d
 11103:   //  n桁10進数変換(符号あり,ゼロサプレスあり)
 11104:   //  n桁に収まらないとき右側にはみ出すのでバッファのサイズに注意
 11105:   public static int fmtCAnd (char[] a, int o, int n, long x) {
 11106:     int t = fmtCAd (a, o, x);  //現在の末尾
 11107:     n += o;  //必要な末尾
 11108:     if (t < n) {  //余っている
 11109:       int i = n;
 11110:       while (o < t) {  //右から順に右にずらす
 11111:         a[--i] = a[--t];
 11112:       }
 11113:       while (o < i) {  //左にできた隙間を' 'で埋める
 11114:         a[--i] = ' ';
 11115:       }
 11116:       t = n;
 11117:     }
 11118:     return t;
 11119:   }  //fmtnu(char[],int,int,long)
 11120:   public static StringBuilder fmtSBnd (StringBuilder sb, int n, int x) {
 11121:     return sb.append (FMT_TEMP, 0, fmtCAnd (FMT_TEMP, 0, n, x));
 11122:   }  //fmtSBnu(StringBuilder,int,long)
 11123: 
 11124:   //--------------------------------------------------------------------------------
 11125:   //10進数文字列解析
 11126: 
 11127:   //x = fmtParseInt (s, i, min, max, err)
 11128:   //  文字列sのインデックスiから基数10で整数xを読み取る
 11129:   //x = fmtParseIntRadix (s, i, min, max, err, radix)
 11130:   //  文字列sのインデックスiから基数radixで整数xを読み取る
 11131:   //  基数radixは2,8,10,16のいずれかに限る
 11132:   //  1文字も読み取れないかmin<=x&&x<=maxでないときはerrを返す
 11133:   //  先頭の空白を読み飛ばす
 11134:   //  数値の先頭の'$'は16進数の強制指定とみなす
 11135:   //  数値の後のゴミは無視する
 11136:   public static int fmtParseInt (String s, int i, int min, int max, int err) {
 11137:     return fmtParseIntRadix (s, i, min, max, err, 10);
 11138:   }  //fmtParseInt(String,int,int,int,int)
 11139:   public static int fmtParseIntRadix (String s, int i, int min, int max, int err, int radix) {
 11140:     if (s == null) {
 11141:       return err;
 11142:     }
 11143:     int l = s.length ();
 11144:     int c = i < l ? s.charAt (i++) : -1;
 11145:     //空白を読み飛ばす
 11146:     while (c == ' ' || c == '\t') {
 11147:       c = i < l ? s.charAt (i++) : -1;
 11148:     }
 11149:     //符号を読み取る
 11150:     int n = 0;
 11151:     if (c == '+') {
 11152:       c = i < l ? s.charAt (i++) : -1;
 11153:     } else if (c == '-') {
 11154:       n = 1;
 11155:       c = i < l ? s.charAt (i++) : -1;
 11156:     }
 11157:     //基数を読み取る
 11158:     //        2進数の範囲        8進数の範囲       10進数の範囲        16進数の範囲
 11159:     //  +    0x3fffffff*2+1     0x0fffffff*8+7     214748364*10+7     0x07ffffff*16+15
 11160:     //  -  -(0x40000000*2+0)  -(0x10000000*8+0)  -(214748364*10+8)  -(0x08000000*16+ 0)
 11161:     int o;
 11162:     int p;
 11163:     if (c == '$') {  //16進数
 11164:       o = 0x07ffffff + n;
 11165:       p = 15 + n & 15;
 11166:       radix = 16;
 11167:       c = i < l ? s.charAt (i++) : -1;
 11168:     } else if (radix == 16) {  //16進数
 11169:       o = 0x07ffffff + n;
 11170:       p = 15 + n & 15;
 11171:     } else if (radix == 8) {  //8進数
 11172:       o = 0x0fffffff + n;
 11173:       p = 7 + n & 7;
 11174:     } else if (radix == 2) {  //2進数
 11175:       o = 0x3fffffff + n;
 11176:       p = 1 + n & 1;
 11177:     } else {  //10進数
 11178:       o = 214748364;
 11179:       p = 7 + n;
 11180:       radix = 10;
 11181:     }
 11182:     //数値を読み取る
 11183:     int x = Character.digit (c, radix);
 11184:     if (x < 0) {
 11185:       return err;
 11186:     }
 11187:     c = i < l ? Character.digit (s.charAt (i++), radix) : -1;
 11188:     while (c >= 0) {
 11189:       int t = x - o;
 11190:       if (t > 0 || t == 0 && c > p) {
 11191:         return err;
 11192:       }
 11193:       x = x * radix + c;
 11194:       c = i < l ? Character.digit (s.charAt (i++), radix) : -1;
 11195:     }
 11196:     if (n != 0) {
 11197:       x = -x;
 11198:     }
 11199:     return min <= x && x <= max ? x : err;
 11200:   }  //fmtParseIntRadix(String,int,int,int,int,int)
 11201: 
 11202: 
 11203: 
 11204:   //========================================================================================
 11205:   //$$MAT 数学関数
 11206: 
 11207:   //x = matMax3 (x1, x2, x3)
 11208:   //x = matMax4 (x1, x2, x3, x4)
 11209:   //x = matMax5 (x1, x2, x3, x4, x5)
 11210:   //  最大値
 11211:   public static long matMax3 (long x1, long x2, long x3) {
 11212:     return Math.max (Math.max (x1, x2), x3);
 11213:   }  //matMax3(long,long,long)
 11214:   public static long matMax4 (long x1, long x2, long x3, long x4) {
 11215:     return Math.max (Math.max (x1, x2), Math.max (x3, x4));
 11216:   }  //matMax4(long,long,long,long)
 11217:   public static long matMax5 (long x1, long x2, long x3, long x4, long x5) {
 11218:     return Math.max (Math.max (Math.max (x1, x2), Math.max (x3, x4)), x5);
 11219:   }  //matMax5(long,long,long,long,long)
 11220: 
 11221:   //x = matMin3 (x1, x2, x3)
 11222:   //x = matMin4 (x1, x2, x3, x4)
 11223:   //x = matMin5 (x1, x2, x3, x4, x5)
 11224:   //  最小値
 11225:   public static long matMin3 (long x1, long x2, long x3) {
 11226:     return Math.min (Math.min (x1, x2), x3);
 11227:   }  //matMin3(long,long,long)
 11228:   public static long matMin4 (long x1, long x2, long x3, long x4) {
 11229:     return Math.min (Math.min (x1, x2), Math.min (x3, x4));
 11230:   }  //matMin4(long,long,long,long)
 11231:   public static long matMin5 (long x1, long x2, long x3, long x4, long x5) {
 11232:     return Math.min (Math.min (Math.min (x1, x2), Math.min (x3, x4)), x5);
 11233:   }  //matMin5(long,long,long,long,long)
 11234: 
 11235: 
 11236: 
 11237:   //========================================================================================
 11238:   //$$STR 文字列
 11239: 
 11240:   //s = encodeUTF8 (s)
 11241:   //  UTF-8変換
 11242:   //  00000000 00000000 00000000 0xxxxxxx => 00000000 00000000 00000000 0xxxxxxx
 11243:   //  00000000 00000000 00000xxx xxyyyyyy => 00000000 00000000 110xxxxx 10yyyyyy
 11244:   //  00000000 00000000 xxxxyyyy yyzzzzzz => 00000000 1110xxxx 10yyyyyy 10zzzzzz
 11245:   //  00000000 000xxxyy yyyyzzzz zzxxxxxx => 11110xxx 10yyyyyy 10zzzzzz 10xxxxxx
 11246:   public static String strEncodeUTF8 (String s) {
 11247:     StringBuilder sb = new StringBuilder ();
 11248:     int l = s.length ();
 11249:     for (int i = 0; i < l; i++) {
 11250:       int u = s.charAt (i);
 11251:       if (0xd800 <= u && u <= 0xdbff && i + 1 < l) {
 11252:         int v = s.charAt (i + 1);
 11253:         if (0xdc00 <= v && v <= 0xdfff) {  //surrogate pair
 11254:           u = 0x10000 + ((u & 0x3ff) << 10) + (v & 0x3ff);
 11255:           i++;
 11256:         }
 11257:       }
 11258:       if ((u & 0xffffff80) == 0) {  //7bit
 11259:         sb.append ((char) u);
 11260:       } else if ((u & 0xfffff800) == 0) {  //11bit
 11261:         u = (0x0000c080 |
 11262:              (u & 0x000007c0) << 2 |
 11263:              (u & 0x0000003f));
 11264:         sb.append ((char) (u >> 8)).append ((char) (u & 0xff));
 11265:       } else if ((u & 0xffff0000) == 0 && !(0xd800 <= u && u <= 0xdfff)) {  //16bit except broken surrogate pair
 11266:         u = (0x00e08080 |
 11267:              (u & 0x0000f000) << 4 |
 11268:              (u & 0x00000fc0) << 2 |
 11269:              (u & 0x0000003f));
 11270:         sb.append ((char) (u >> 16)).append ((char) ((u >> 8) & 0xff)).append ((char) (u & 0xff));
 11271:       } else if ((u & 0xffe00000) == 0) {  //21bit
 11272:         u = (0xf0808080 |
 11273:              (u & 0x001c0000) << 6 |
 11274:              (u & 0x0003f000) << 4 |
 11275:              (u & 0x00000fc0) << 2 |
 11276:              (u & 0x0000003f));
 11277:         sb.append ((char) ((u >> 24) & 0xff)).append ((char) ((u >> 16) & 0xff)).append ((char) ((u >> 8) & 0xff)).append ((char) (u & 0xff));
 11278:       } else {  //out of range or broken surrogate pair
 11279:         sb.append ((char) 0xef).append ((char) 0xbf).append ((char) 0xbd);  //U+FFFD REPLACEMENT CHARACTER
 11280:       }
 11281:     }
 11282:     return sb.toString ();
 11283:   }  //encodeUTF8(String)
 11284: 
 11285:   //s = decodeUTF8 (s)
 11286:   //  UTF-8逆変換
 11287:   //  00000000 00000000 00000000 0xxxxxxx => 00000000 00000000 00000000 0xxxxxxx
 11288:   //  00000000 00000000 110xxxxx 10yyyyyy => 00000000 00000000 00000xxx xxyyyyyy
 11289:   //  00000000 1110xxxx 10yyyyyy 10zzzzzz => 00000000 00000000 xxxxyyyy yyzzzzzz
 11290:   //  11110xxx 10yyyyyy 10zzzzzz 10xxxxxx => 00000000 000xxxyy yyyyzzzz zzxxxxxx
 11291:   public static String strDecodeUTF8 (String s) {
 11292:     StringBuilder sb = new StringBuilder ();
 11293:     int l = s.length ();
 11294:     for (int i = 0; i < l; i++) {
 11295:       int c = s.charAt (i) & 0xff;
 11296:       for (int k = ((c & 0x80) == 0x00 ? 0 :  //0xxxxxxx 7bit
 11297:                     (c & 0xe0) == 0xc0 ? 1 :  //110xxxxx 11bit
 11298:                     (c & 0xf0) == 0xe0 ? 2 :  //1110xxxx 16bit
 11299:                     (c & 0xf8) == 0xf0 ? 3 :  //11110xxx 21bit
 11300:                     -1);  //not supported
 11301:            --k >= 0; ) {
 11302:         c = c << 8 | (i + 1 < l ? s.charAt (++i) & 0xff : 0);
 11303:       }
 11304:       int u = ((c & 0xffffff80) == 0x00000000 ? c :
 11305:                (c & 0xffffe0c0) == 0x0000c080 ? ((c & 0x00001f00) >> 2 |
 11306:                                                  (c & 0x0000003f)) :
 11307:                (c & 0xfff0c0c0) == 0x00e08080 ? ((c & 0x000f0000) >> 4 |
 11308:                                                  (c & 0x00003f00) >> 2 |
 11309:                                                  (c & 0x0000003f)) :
 11310:                (c & 0xf8c0c0c0) == 0xf0808080 ? ((c & 0x07000000) >> 6 |
 11311:                                                  (c & 0x003f0000) >> 4 |
 11312:                                                  (c & 0x00003f00) >> 2 |
 11313:                                                  (c & 0x0000003f)) :
 11314:                0xfffd);  //U+FFFD REPLACEMENT CHARACTER
 11315:       if (u <= 0x0000ffff) {
 11316:         sb.append (0xd800 <= u && u <= 0xdfff ? '\ufffd' :  //U+FFFD REPLACEMENT CHARACTER
 11317:                    (char) u);
 11318:       } else if (u <= 0x0010ffff) {
 11319:         u -= 0x000010000;
 11320:         sb.append ((char) (0xd800 + ((u >> 10) & 0x3ff))).append ((char) (0xdc00 + (u & 0x3ff)));
 11321:       }
 11322:     }
 11323:     return sb.toString ();
 11324:   }  //decodeUTF8(String)
 11325: 
 11326:   //uri = strEncodeURI (s)
 11327:   //  URI変換
 11328:   //  UTF-8変換を行ってからRFC3986のPercent-Encodingを行う
 11329:   //  フォームの送信に使用されるapplication/x-www-form-urlencodedではない。" "は"+"ではなく"%20"に変換される
 11330:   public static final int[] IsURIChar = {  //URIに使える文字。RFC3986のUnreserved Characters。[-.0-9A-Z_a-z~]
 11331:     //00000000 00000000 11111111 11111111
 11332:     //01234567 89abcdef 01234567 89abcdef
 11333:     0b00000000_00000000_00000000_00000000,  //0x00..0x1f
 11334:     0b00000000_00000110_11111111_11000000,  //0x20..0x3f [-.0-9]
 11335:     0b01111111_11111111_11111111_11100001,  //0x40..0x5f [A-Z_]
 11336:     0b01111111_11111111_11111111_11100010,  //0x60..0x7f [a-z~]
 11337:   };
 11338:   public static String strEncodeURI (String s) {
 11339:     s = strEncodeUTF8 (s);  //UTF-8変換
 11340:     StringBuilder sb = new StringBuilder ();
 11341:     int l = s.length ();
 11342:     for (int i = 0; i < l; i++) {
 11343:       int c = s.charAt (i);
 11344:       if (c < 0x80 && IsURIChar[c >> 5] << c < 0) {  //URIに使える文字
 11345:         sb.append ((char) c);
 11346:       } else {
 11347:         fmtHex2 (sb.append ('%'), c);
 11348:       }
 11349:     }
 11350:     return sb.toString ();
 11351:   }  //encodeURI(String)
 11352: 
 11353:   //s = strDecodeURI (s)
 11354:   //  URI逆変換
 11355:   //  RFC3986のPercent-Encodingの逆変換を行ってからUTF-8逆変換を行う
 11356:   //  フォームの送信に使用されるapplication/x-www-form-urlencodedではない。"+"は" "に変換されない
 11357:   public static final byte[] strIsHexChar = {  //16進数に使えるASCII文字。[0-9A-Fa-f]
 11358:     // 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f 10 11 12 13 14 15 16 17 18 19 1a 1b 1c 1d 1e 1f
 11359:     -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,  //0x00..0x1f
 11360:     -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,-1,-1,-1,-1,-1,-1,  //0x20..0x3f [0-9]
 11361:     -1,10,11,12,13,14,15,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,  //0x40..0x5f [A-F]
 11362:     -1,10,11,12,13,14,15,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,  //0x60..0x7f [a-f]
 11363:   };
 11364:   public static String strDecodeURI (String s) {
 11365:     StringBuilder sb = new StringBuilder ();
 11366:     int l = s.length ();
 11367:     for (int i = 0; i < l; i++) {
 11368:       int c = s.charAt (i);
 11369:       if (c == '%' && i + 2 < l) {
 11370:         int d = s.charAt (i + 1);
 11371:         int e = s.charAt (i + 2);
 11372:         if (d < 0x80 && (d = strIsHexChar[d]) >= 0 &&
 11373:             e < 0x80 && (e = strIsHexChar[e]) >= 0) {
 11374:           sb.append ((char) (d << 4 | e));
 11375:         } else {
 11376:           sb.append ((char) c);
 11377:         }
 11378:       } else {
 11379:         sb.append ((char) c);
 11380:       }
 11381:     }
 11382:     return sb.toString ();
 11383:   }  //decodeURI(String)
 11384: 
 11385: 
 11386: 
 11387:   //========================================================================================
 11388:   //$$IMG イメージ
 11389: 
 11390:   //image = createImage (width, height, pattern, rgb, ...)
 11391:   //  イメージを作る
 11392:   public static BufferedImage createImage (int width, int height, String pattern, int... rgbs) {
 11393:     BufferedImage image = new BufferedImage (width, height, BufferedImage.TYPE_INT_RGB);
 11394:     int[] bitmap = ((DataBufferInt) image.getRaster ().getDataBuffer ()).getData ();
 11395:     int length = width * height;
 11396:     for (int i = 0; i < length; i++) {
 11397:       char c = pattern.charAt (i);
 11398:       bitmap[i] = rgbs[c < '0' ? 0 : Character.digit (c, 16)];
 11399:     }
 11400:     return image;
 11401:   }  //createImage(int,int,String,int...)
 11402: 
 11403:   //icon = createImageIcon (width, height, pattern, rgb, ...)
 11404:   //  イメージアイコンを作る
 11405:   public static ImageIcon createImageIcon (int width, int height, String pattern, int... rgbs) {
 11406:     return new ImageIcon (createImage (width, height, pattern, rgbs));
 11407:   }  //createImageIcon(int,int,String,int...)
 11408: 
 11409:   //paint = createTexturePaint (width, height, pattern, rgb, ...)
 11410:   //  テクスチャペイントを作る
 11411:   public static TexturePaint createTexturePaint (int width, int height, String pattern, int... rgbs) {
 11412:     return new TexturePaint (createImage (width, height, pattern, rgbs), new Rectangle (0, 0, width, height));
 11413:   }  //createTexturePaint(int,int,String,int...)
 11414: 
 11415:   //image = loadImage (name)
 11416:   //  イメージを読み込む
 11417:   public static BufferedImage loadImage (String name) {
 11418:     BufferedImage image = null;
 11419:     try {
 11420:       image = ImageIO.read (new File (name));
 11421:     } catch (Exception e) {
 11422:     }
 11423:     return image;
 11424:   }  //loadImage(String)
 11425: 
 11426:   //sucess = saveImage (image, name)
 11427:   //sucess = saveImage (image, name, quality)
 11428:   //  イメージを書き出す
 11429:   public static boolean saveImage (BufferedImage image, String name) {
 11430:     return saveImage (image, name, 0.75F);
 11431:   }  //saveImage(BufferedImage,String)
 11432:   public static boolean saveImage (BufferedImage image, String name, float quality) {
 11433:     int index = name.lastIndexOf (".");
 11434:     if (index < 0) {  //拡張子がない
 11435:       return false;
 11436:     }
 11437:     if (name.substring (index).equalsIgnoreCase (".ico")) {  //アイコンファイルの作成
 11438:       return saveIcon (name, image);
 11439:     }
 11440:     Iterator<ImageWriter> iterator = ImageIO.getImageWritersBySuffix (name.substring (index + 1));  //拡張子に対応するImageWriterがないときは空のIteratorを返す
 11441:     if (!iterator.hasNext ()) {  //拡張子に対応するImageWriterがない
 11442:       return false;
 11443:     }
 11444:     ImageWriter imageWriter = iterator.next ();
 11445:     ImageWriteParam imageWriteParam = imageWriter.getDefaultWriteParam ();
 11446:     if (imageWriteParam.canWriteCompressed ()) {
 11447:       imageWriteParam.setCompressionMode (ImageWriteParam.MODE_EXPLICIT);
 11448:       imageWriteParam.setCompressionQuality (quality);
 11449:     }
 11450:     try {
 11451:       File file = new File (name);
 11452:       ImageOutputStream imageOutputStream = ImageIO.createImageOutputStream (file);
 11453:       imageWriter.setOutput (imageOutputStream);
 11454:       imageWriter.write (null, new IIOImage (image, null, null), imageWriteParam);
 11455:       imageOutputStream.close ();
 11456:     } catch (Exception e) {
 11457:       //e.printStackTrace ();
 11458:       return false;
 11459:     }
 11460:     return true;
 11461:   }  //saveImage(BufferedImage,String,float)
 11462: 
 11463: 
 11464: 
 11465:   //========================================================================================
 11466:   //$$ICO アイコンファイル
 11467:   //  サイズの異なる複数のアイコンを格納することができる
 11468:   //  ワードサイズとロングサイズのデータはすべてリトルエンディアン
 11469:   //
 11470:   //  アイコンファイル(.ico)
 11471:   //    ファイルヘッダ
 11472:   //    エントリデータ0
 11473:   //           :
 11474:   //    エントリデータn-1
 11475:   //    イメージデータ0
 11476:   //           :
 11477:   //    イメージデータn-1
 11478:   //
 11479:   //  ファイルヘッダ
 11480:   //    0000  .iw  0=予約
 11481:   //    0002  .iw  1=アイコン
 11482:   //    0004  .iw  n=アイコン数
 11483:   //    0006
 11484:   //
 11485:   //  エントリデータ
 11486:   //    0000  .b   幅
 11487:   //    0001  .b   高さ
 11488:   //    0002  .b   色数(0=256以上)
 11489:   //    0003  .b   0=予約
 11490:   //    0004  .iw  1=プレーン数
 11491:   //    0006  .iw  ピクセル毎のビット数
 11492:   //    0008  .il  イメージデータの長さ
 11493:   //    000c  .il  ファイルヘッダからイメージデータまでのオフセット
 11494:   //    0010
 11495:   //
 11496:   //  イメージデータ
 11497:   //    イメージヘッダ
 11498:   //    パレットテーブル
 11499:   //    パターンデータ
 11500:   //    マスクデータ
 11501:   //
 11502:   //  イメージヘッダ
 11503:   //    0000  .il  40=イメージヘッダの長さ
 11504:   //    0004  .il  幅
 11505:   //    0008  .il  高さ*2
 11506:   //    000c  .iw  1=プレーン数
 11507:   //    000e  .iw  ピクセル毎のビット数
 11508:   //    0010  .il  0=無圧縮
 11509:   //    0014  .il  0=画像データサイズ(省略)
 11510:   //    0018  .il  0=横解像度(省略)
 11511:   //    001c  .il  0=縦解像度(省略)
 11512:   //    0020  .il  p=パレット数
 11513:   //    0024  .il  0=重要なパレットのインデックス(省略)
 11514:   //    0028
 11515:   //
 11516:   //  パレットテーブル
 11517:   //    0000  .il  パレット0(BGR0)
 11518:   //                   :
 11519:   //          .il  パレットp-1(BGR0)
 11520:   //    4*p
 11521:   //
 11522:   //  パターンデータ
 11523:   //    ピクセルの順序は左下から右上
 11524:   //    バイト内のビットの順序は上位から下位
 11525:   //    1ラインのデータ長は4の倍数
 11526:   //
 11527:   //  マスクデータ
 11528:   //    0=描画,1=透過
 11529:   //    ピクセルの順序は左下から右上
 11530:   //    バイト内のビットの順序は上位から下位
 11531:   //    1ラインのデータ長は4の倍数
 11532: 
 11533:   //success = saveIcon (name, image, ...);
 11534:   //  アイコンファイルを出力する
 11535:   public static boolean saveIcon (String fileName, BufferedImage... arrayImage) {
 11536:     int iconCount = arrayImage.length;
 11537:     int[][] arrayPaletTable = new int[iconCount][];  //パレットテーブル
 11538:     int[] arrayPaletCount = new int[iconCount];  //パレット数。0=パレットを使わない
 11539:     int[] arrayPixelBits = new int[iconCount];  //ピクセル毎のビット数。24,8,4,2,1のいずれか
 11540:     int[] arrayPatternLineSize = new int[iconCount];  //パターンデータの1ラインのバイト数
 11541:     int[] arrayMaskLineSize = new int[iconCount];  //マスクデータの1ラインのバイト数
 11542:     int[] arrayImageSize = new int[iconCount];  //イメージデータの長さ
 11543:     int[] arrayImageOffset = new int[iconCount];  //ファイルヘッダからイメージデータまでのオフセット
 11544:     int fileSize = 6 + 16 * iconCount;
 11545:     for (int iconNumber = 0; iconNumber < iconCount; iconNumber++) {
 11546:       BufferedImage image = arrayImage[iconNumber];
 11547:       int width = image.getWidth ();
 11548:       int height = image.getHeight ();
 11549:       //パレットテーブルを作る
 11550:       int[] paletTable = new int[256];
 11551:       int paletCount = 0;
 11552:     countPalet:
 11553:       for (int y = height - 1; y >= 0; y--) {
 11554:         for (int x = 0; x < width; x++) {
 11555:           int rgb = image.getRGB (x, y);
 11556:           if (rgb >>> 24 != 0xff) {  //alphaが0xffでなければred,green,blueを無視して透過色とみなす
 11557:             continue;
 11558:           }
 11559:           int l = 0;
 11560:           int r = paletCount;
 11561:           while (l < r) {
 11562:             int m = l + r >> 1;
 11563:             if (paletTable[m] < rgb) {
 11564:               l = m + 1;
 11565:             } else {
 11566:               r = m;
 11567:             }
 11568:           }
 11569:           if (l == paletCount || paletTable[l] != rgb) {  //新しい色
 11570:             if (paletCount == 256) {  //色数が多すぎる
 11571:               paletCount = 0;
 11572:               break countPalet;
 11573:             }
 11574:             for (int i = paletCount; i > l; i--) {
 11575:               paletTable[i] = paletTable[i - 1];
 11576:             }
 11577:             paletTable[l] = rgb;
 11578:             paletCount++;
 11579:           }
 11580:         }  //for x
 11581:       }  //for y
 11582:       int pixelBits = (paletCount == 0 ? 24 :
 11583:                        paletCount > 16 ? 8 :
 11584:                        paletCount > 4 ? 4 :
 11585:                        paletCount > 2 ? 2 :
 11586:                        1);
 11587:       int patternLineSize = pixelBits * width + 31 >> 5 << 2;
 11588:       int maskLineSize = width + 31 >> 5 << 2;
 11589:       int imageSize = 40 + 4 * paletCount + patternLineSize * height + maskLineSize * height;
 11590:       arrayPaletTable[iconNumber] = paletTable;
 11591:       arrayPaletCount[iconNumber] = paletCount;
 11592:       arrayPixelBits[iconNumber] = pixelBits;
 11593:       arrayPatternLineSize[iconNumber] = patternLineSize;
 11594:       arrayMaskLineSize[iconNumber] = maskLineSize;
 11595:       arrayImageSize[iconNumber] = imageSize;
 11596:       arrayImageOffset[iconNumber] = fileSize;
 11597:       fileSize += imageSize;
 11598:     }  //for iconNumber
 11599:     byte[] bb = new byte[fileSize];
 11600:     //ファイルヘッダ
 11601:     ByteArray.byaWiw (bb, 0, 0);
 11602:     ByteArray.byaWiw (bb, 2, 1);
 11603:     ByteArray.byaWiw (bb, 4, iconCount);
 11604:     for (int iconNumber = 0; iconNumber < iconCount; iconNumber++) {
 11605:       BufferedImage image = arrayImage[iconNumber];
 11606:       int width = image.getWidth ();
 11607:       int height = image.getHeight ();
 11608:       int[] paletTable = arrayPaletTable[iconNumber];
 11609:       int paletCount = arrayPaletCount[iconNumber];
 11610:       int pixelBits = arrayPixelBits[iconNumber];
 11611:       int patternLineSize = arrayPatternLineSize[iconNumber];
 11612:       int maskLineSize = arrayMaskLineSize[iconNumber];
 11613:       int imageSize = arrayImageSize[iconNumber];
 11614:       int imageOffset = arrayImageOffset[iconNumber];
 11615:       //エントリデータ
 11616:       int o = 6 + 16 * iconNumber;
 11617:       ByteArray.byaWb (bb, o, width);
 11618:       ByteArray.byaWb (bb, o + 1, height);
 11619:       ByteArray.byaWb (bb, o + 2, paletCount);
 11620:       ByteArray.byaWb (bb, o + 3, 0);
 11621:       ByteArray.byaWiw (bb, o + 4, 1);
 11622:       ByteArray.byaWiw (bb, o + 6, pixelBits);
 11623:       ByteArray.byaWil (bb, o + 8, imageSize);
 11624:       ByteArray.byaWil (bb, o + 12, imageOffset);
 11625:       //イメージヘッダ
 11626:       o = imageOffset;
 11627:       ByteArray.byaWil (bb, o, 40);
 11628:       ByteArray.byaWil (bb, o + 4, width);
 11629:       ByteArray.byaWil (bb, o + 8, height * 2);
 11630:       ByteArray.byaWiw (bb, o + 12, 1);
 11631:       ByteArray.byaWiw (bb, o + 14, pixelBits);
 11632:       ByteArray.byaWil (bb, o + 16, 0);
 11633:       ByteArray.byaWil (bb, o + 20, 0);
 11634:       ByteArray.byaWil (bb, o + 24, 0);
 11635:       ByteArray.byaWil (bb, o + 28, 0);
 11636:       ByteArray.byaWil (bb, o + 32, paletCount);
 11637:       ByteArray.byaWil (bb, o + 36, 0);
 11638:       //パレットテーブル
 11639:       o += 40;
 11640:       for (int i = 0; i < paletCount; i++) {
 11641:         ByteArray.byaWil (bb, o, paletTable[i] & 0x00ffffff);
 11642:         o += 4;
 11643:       }
 11644:       //パターンデータ
 11645:       for (int y = height - 1; y >= 0; y--) {
 11646:         for (int x = 0; x < width; x++) {
 11647:           int rgb = image.getRGB (x, y);
 11648:           if (rgb >>> 24 != 0xff) {  //alphaが0xffでなければred,green,blueを無視して透過色とみなす
 11649:             continue;
 11650:           }
 11651:           if (pixelBits == 24) {  //パレットなし
 11652:             bb[o + 3 * x] = (byte) rgb;  //blue
 11653:             bb[o + 3 * x + 1] = (byte) (rgb >> 8);  //green
 11654:             bb[o + 3 * x + 2] = (byte) (rgb >> 16);  //red
 11655:             continue;
 11656:           }
 11657:           int l = 0;
 11658:           int r = paletCount;
 11659:           while (l < r) {
 11660:             int m = l + r >> 1;
 11661:             if (paletTable[m] < rgb) {
 11662:               l = m + 1;
 11663:             } else {
 11664:               r = m;
 11665:             }
 11666:           }
 11667:           if (l != 0) {
 11668:             if (pixelBits == 8) {
 11669:               bb[o + x] = (byte) l;
 11670:             } else if (pixelBits == 4) {
 11671:               bb[o + (x >> 1)] |= (byte) (l << ((~x & 1) << 2));
 11672:             } else if (pixelBits == 2) {
 11673:               bb[o + (x >> 2)] |= (byte) (l << ((~x & 3) << 1));
 11674:             } else {
 11675:               bb[o + (x >> 3)] |= (byte) (l << (~x & 7));
 11676:             }
 11677:           }
 11678:         }  //for x
 11679:         o += patternLineSize;
 11680:       }  //for y
 11681:       //マスクデータ
 11682:       for (int y = height - 1; y >= 0; y--) {
 11683:         for (int x = 0; x < width; x++) {
 11684:           int rgb = image.getRGB (x, y);
 11685:           if (rgb >>> 24 != 0xff) {  //alphaが0xffでなければred,green,blueを無視して透過色とみなす
 11686:             bb[o + (x >> 3)] |= (byte) (1 << (~x & 7));
 11687:           }
 11688:         }
 11689:         o += maskLineSize;
 11690:       }
 11691:     }  //for iconNumber
 11692:     return rscPutFile (fileName, bb, 0, fileSize);
 11693:   }  //saveIcon(String,BufferedImage...)
 11694: 
 11695: 
 11696: 
 11697: }  //class XEiJ
 11698: 
 11699: 
 11700: