トップ 差分 一覧 ソース 検索 ヘルプ RSS ログイン

1章 ブートシーケンス

 MSX2とMSX2+では、システムソフトウェアはMAIN ROMとSUB ROMに分かれています。また、ディスクを搭載したシステムの場合は、DISK ROMもシステムソフトウェアとして内蔵されています。

 この章ではこれらのシステムソフトウェアが、実際に行う初期化の手順について解説します。

 1.1 MAIN ROMでの初期化

 MAIN ROMは以下の手順で初期化を行います。

  1. マッパーおよびPPIの初期化
  2. RAMのサーチ
  3. システムワークエリアの初期化
  4. SUB ROMのサーチ
  5. ROMのサーチ
  6. スクリーンの設定

1.1.1 マッパーおよびPPIの初期化

表2.1 マッパーI/Oポートの初期値

I/Oポートデータ
0FFH00H
0FEH01H
0FDH02H
0FCH03H
0ABH82H
0A8H00H

 ポート0FCHから0FFHはそれぞれページ0から3に現れるマッパーセグメントを指定するレジスタです。つまり、

ページ3セグメント0
ページ2セグメント1
ページ1セグメント2
ページ0セグメント3

が現れるように設定されます。

 ポート0ABHはPPI(i8255)のモード設定レジスタで、ポート0A8Hが出力、ポート0A9Hが入力、ポート0AAHが出力に設定されます。

 ポート0A8Hは基本スロットを選択するレジスタで、00Hを出力することにより、ページ0、1にMAIN ROMが現れることになります。

1.1.2 RAMのサーチ

 MSXではRAMの存在するスロットを特に規定していないので、RAMのあるスロットを捜さなければなりません。RAMのページは2、3の順番で捜します。

 ページ2のRAMはすべてのスロットに対し、以下の順番でチェックします。

0BF00Hから0BFFFHまで1バイトずつ上位アドレス方向に
0BE00Hから0BEFFHまで1バイトずつ上位アドレス方向に
                     :
                     :
08000Hから080FFHまで1バイトずつ上位アドレス方向に

チェックは

  1. 1バイト読み出す
  2. 1の補数を取る
  3. その結果を書き込む
  4. それを比較する
  5. データを元に戻す

という手順で行いますので、元の内容が破壊されることはありません。途中でRAMが実装されていない(正しく比較されなかった)と判断された時点で、そのスロットに対するチェックは中断します。

 これを全てのスロットに対して繰り返し、最大の容量を持つスロット(同じ容量のスロットが存在する場合は、スロット番号の若いもの)が選択され、ページ2に現れます。

 基本スロットが拡張されたスロットであるかどうかの判断も、ページ2のRAMチェックと同時に行います。拡張スロットセレクトレジスタは、「書き込んだ値の1の補数が読み込まれる」と規定されていることを利用して拡張されているかどうかのチェックをしています。

 ページ3のRAMも同じような手順で捜しますが、アドレスが以下のようになります。

0FE00Hから0FEFFHまで1バイトずつ上位アドレス方向に
0FD00Hから0FDFFHまで1バイトずつ上位アドレス方向に
                     :
                     :
0C000Hから0C0FFHまで1バイトずつ上位アドレス方向に

このようにして見つかったページ3のRAMがシステムのワークエリアとして使用されます。

1.1.3 システムワークエリアの初期化

 ワークエリアの初期化はまず0F380Hから0FFF7Hまでを0でクリアすることから始まります。その後、「1.1.2 RAMのサーチ」で得られた拡張スロットに関する情報を【EXPTBL(0FCC1H〜0FCC4H)】と【SLTTBL(0FCC5H〜0FCC8H)】に書き込みます。その他の初期値はテーブルからブロック転送するかプログラムにより設定します。

 次に、ページ2と3で連続して実装されているRAM容量のチェックを行い、【BOTTOM(0FC48H)】という変数を設定します。RAMチェックの順番は以下の通りです。このときも元の内容は破壊されません。

0FE00Hから0FEFFHまで1バイトずつ上位アドレス方向に
0FD00Hから0FDFFHまで1バイトずつ上位アドレス方向に
                     :
                     :
08000Hから080FFHまで1バイトずつ上位アドレス方向に

1.1.4 SUB ROMのサーチ

 MSX2ではSUB ROMの存在するスロットは規定されていないので、SUB ROMを捜さなければなりません。SUB ROMは、

アドレスがページ0で、ROMのIDが「CD」の特殊なROMカートリッジ

です。普通のROMカートリッジと同様に、INITエントリ、STATEMENTエントリ、DEVICEエントリを持ちます。TEXTエントリは持つことができません。
 SUB ROMでの初期化については、「1.2 SUB ROMでの初期化」で解説します。

1.1.5 ROMのサーチ

 次に、MSXはROMカートリッジを捜しますが、MSX2+(BASIC version 3.0)の場合はその前にMAIN ROMの1472H番地を経由します。ここには標準的には4バイトのNOP命令が書いてあるだけです。ハードウェアメーカーが他のスロットに優先して立ち上がるような内蔵ソフトを作りたいときには、このNOPを適当なインタースロットコール命令に置き換えれば実現できることになります。

 ROMはスロット番号の若い順に、4000H、8000H番地の順で、ROMのID(「AB」)が書いてあるかどうかを調べます。

 ROM IDが見つかれば、INITエントリを調べ、0以外ならその番地をインタースロットコールします。もし、このROMがゲームのような、ROM内だけでループして動くソフトであったら、システムに制御が帰ってくることがありません。

 次に、STATEMENTエントリ、DEVICEエントリ、TEXTエントリを調べ、0以外であったらそのスロットに相当する【SLTATR(0FCC9H〜0FD08H)】のそれぞれBIT5、6、7をセットします。

 これを全てのスロットに対して繰り返します。

1.1.6 スクリーンの設定

 クロックICにはバッテリでバックアップされたRAMが内蔵されていて、MSX2ではデフォルトのスクリーンモードなどが設定されています。ここではそのRAMの内容にしたがって各種のスクリーンモードを設定します。

 1.2 SUB ROMでの初期化

 SUB ROMの初期化プログラムはINITエントリから起動されます。その内容は以下の通りです。

  1. システムワークエリアの初期化
  2. システムコントロールポートの設定
  3. クロックICの初期化
  4. タイトル表示

1.2.1 システムワークエリアの初期化

 MAIN ROMの初期化では不十分な部分を初期化します。

1.2.2 システムコントロールポートの設定

 MSX2では、複数デバイスの競合による不都合を避けるため、標準的な内蔵デバイスに対して、その機能を禁止する機能があり、ポートの0F5Hがそれにあたります。内蔵デバイスはこのポートの対応するビットに1が書かれたときだけ機能するように設計されています。

表2.2 システムコントロールポートの割り当て

ビット0第1水準漢字ROMのためのビットです。
ビット1MSX2では使用されていませんが、MSX2+では第2水準漢字ROMのためのビットに割り当てられています。
ビット2MSX-AUDIOのためのビットです。ポート0C0Hが0FFH以外であったらMSX-AUDIOが存在すると判定されます。
ビット3AVコントロールのためのビットです。ポート0F7Hと77HをANDしたものが77H以外だったら存在すると判定されます。
ビット4MSX INTERFACEのためのビットです。ポート0C8Hが0FFH以外であったらMSX INTERFACEが存在すると判定されます。MSX INTERFACEは汎用の通信LSIですが、現在のところ使用されていません。
ビット5I/OマップされたRS-232Cインターフェイスのためのビットです。i8251をインターナルリセットした結果、ステータスレジスタがxx000101(2進数)になったら、存在すると判定されます。
ビット6ライトペンのためのビットです。ポート0BBHが0FFH以外であったら存在すると判定されます。
ビット7クロックICのためのビットですが、実際には使用されていません。

 このように、漢字ROM以外のデバイスの判定は、MSXのバスがプルアップされている、つまり存在しないポートを読むと0FFHが返って来ることを前提にしています。

1.2.3 クロックICの初期化

 クロックIC内のRAMは初期化されていない場合もありえますので、ブロック2(RAM-1)の最初の1ニブル(4ビット)が0AHでないか、WIDTH情報が不正(スクリーン0なのに1から80の範囲でない、またはスクリーン1なのに1から32の範囲でない)である場合は、RAMをデフォルトの内容で初期化します。デフォルトの内容は以下のとおりです。

表2.3 クロックIC内RAMの初期値

ADJUST X 0
ADJUST Y 0
スクリーンモード1
WIDTHの値 29
前景色15
背景色4
周辺色7
カセットスピード1200ボー
プリンタモード MSX
キークリック あり
ファンクション表示 あり

1.2.4 タイトル表示

 タイトル表示に関してはMSX2とMSX2+では大きく違いますので、それぞれの場合で解説します。

1. MSX2の場合

 タイトルを表示して(垂直スクロールを使用)、VRAMのサイズを調べます。サイズはVRAMの1FFFFH番地が読み書きできるかどうかで判定します。読み書きできたら128KVRAMで、できなかったら64KVRAMです。その後、VRAMサイズの表示、タイトル(MSXのロゴマーク)の表示、パスワードの表示と入力などを行います。

2. MSX2+の場合

 BIOSのRDRESを呼んでハードウェアリセットであるかどうかを調べます。
ハードウェアリセットでなければ、何もしません。

 ハードウェアリセットなら、メインRAMの総容量を調べ、RAMのIDを消します(これについては後で述べます)。MSX2+ではVRAM容量は128Kに決まっているので調べません。その後、タイトルを表示して(水平スクロールを使用)、メインラムの総容量の表示、タイトルの表示、パスワードの表示と入力などを行います。
 メインRAMの総容量は以下のようにして求めます。

リスト2.1 メインRAMの総容量の算出シーケンス

    総容量 = 0
    全てのスロットに対して{
        ページ1にそのスロットを出す
        セグメント0の第1バイトに0AAHを書く
        セグメント1の第1バイトに055Hを書く
        if セグメント0の第1バイト = 0AAH {
            マッパーの容量 = 0
            全てのセグメントに対して
                 第1バイトに0AAHを書く
            全てのセグメントに対して {
                 if 第1バイト <> 0AAH 
                       break
                 第1バイトに055Hを書く
                 if 第1バイト <> 055H 
                       break
                 マッパーの容量 = マッパーの容量 + 1
            }
            総容量 = 総容量 + マッパー容量
        }
    }

 上記の方法で、マッパー上に存在する全てのRAMの総セグメント数が計算できます。表示されるメインRAM総容量は、総セグメント数の16倍ですが、0の場合は特別に64Kとみなして表示します。これはマッパー回路に接続されていない64KのRAMが存在する場合を考慮したためです。

 RAMのIDの消去は全てのスロットの4000H、8000H番地と、選択されているRAMの0C010H番地に0を書くことにより行われます。これはページ1のRAMにROMのイメージを転送して動作するようなプログラムが、電源をON・OFFしても動いてしまうことを防止するためです。DRAMの中には、電源を切っただけでは内容がなかなか消えないものがあるためこのような方法を取っています。また、0C010Hに0を書くのは、ここをフラグとして使用しているROMのプログラムがあったためです。

 1.3 FDD ROMでの初期化

 ここでは、ディスク環境での立ち上がりシーケンスについて解説します。
ただし、ここで解説するのはDOS1の初期化についてだけです。DOS2は限られた紙面で解説するにはあまりにも複雑で、マスターカートリッジ(後述)を乗っ取ってマスターになるなど本質的なこと以外の部分が多く、理解の妨げになるためです。

 また、この章の内容は、DOSのバージョンアップに伴って変更される可能性がありますので(実際にDOS2では違う)、あくまでも内部動作の理解のために使用して下さい。商用のアプリケーションソフトウェアでは、この内部情報は使用しないで下さい。

 ディスクカートリッジは、MSXにとって特別な地位を約束されているわけではなく、一般のカートリッジと同等の扱いを受けます。ただし、システムに深く密着したソフトウェアですので、MSXで規定されていないRAMのワークエリアなどを使用しています。

 以下にディスクカートリッジのINITエントリで実行される初期化シーケンスを記述します。ここでINIHRD、DRIVES、INIENVはディスクカートリッジ内のディスクドライバのルーチンです。allocは指定されたバイト数だけ上位アドレスから割り当てそこへのポインタを返す内部ルーチン、DISKIDは0FD99H番地の内容で初期値は0、pはポインタ変数、fはフラグ変数です。

 DEFDPBはドライバ内部にある定数テーブルで、少なくともそのテーブルによって、ドライバがサポートしているすべてのメディアのブートセクタおよびFATの第1セクタが読めることが保証されています。【$DPBLIST(0F355H)】はDPBへのポンタを要素とする配列です。

リスト2.2 DISK ROMの初期化シーケンス

   INIHRD()              /* ディスクハードウェア初期化 */
   if DISKID >= 80H
       return
   if DISKID =  0 {
       if SHIFTキーが押されている {
           ビープ
           DISKID = 0FFH
           return
       }
       p = alloc (固定ワークエリアサイズ+ドライバワークエリアサイズ)
       固定ワークエリアを初期化
       f = CONTROLキーが押されている
       ビープ
       H.RUNCの初期化
   } else
       p = alloc (ドライバワークエリアサイズ)
   pをSLTWRKにリンク
   n = DRIVES (f)        /* ドライブ数を返す */
   DRVTBLに設定
   p=alloc ( n * 21 )
   そのカートリッジ内の全てのドライブに対して {
       DEFDPBを p に転送
       p を$DPBLISTにリンク
       p = p + 21
   }
   INIENV()              /* ディスクドライバの環境初期化 */
   DISKID = DISKID + 1

 DISKIDはディスク環境のディスエーブル、および最初のディスクカートリッジであるかどうかの判定に使われます。最初のディスクカートリッジはマスターカートリッジと呼ばれ、ディスク機能の大部分を受け持ちます。他のディスクカートリッジはスレーブカートリッジと呼ばれ、ディスクドライバの部分だけ使用されます。

 マスターカートリッジは【H.RUNC(0FECBH)】というフックを設定します。MSXが全てのカートリッジのスキャンを終えて、BASICを起動する際には必ず呼ばれるフックです。H.RUNCは以下に示すようなルーチンに接続されます。

 【H.STKE(0FEDAH)】はディスクの機能を使用するROMカートリッジが設定するフックです。

リスト2.3 H.RUNCが接続されているルーチン

   変数の初期化
   ドライバ用のセクタバッファ      = alloc (最大セクタサイズ)
   DOS汎用セクタバッファ           = alloc (最大セクタサイズ)
   DOSディレクトリ用セクタバッファ = alloc (最大セクタサイズ)
   全てのドライブについて {
           p = alloc (セクタサイズ * FATサイズ + 1)
           p + 1をそのドライブのDPB内のFATポインタにリンク
   }
   スクリーンの設定
   ページ0、1のRAMを探す
   SP = 0C200H
   if H.STKEが設定されている
           BASIC ROM へジャンプ
   if TEXTエントリを持ったカートリッジがある
           BASIC ROM へジャンプ
   ブートセクタを読み最初の256バイトを0C000Hに転送する
   if ブート不可能
           DISK BASICを起動する
   0C01EHをキャリーフラグをリセットして呼ぶ
   if RAMが64Kない
           DISK BASICを起動する
   ページ0のRAMを表に出す
   ページ0を初期化する
   スロットハンドラを設定する
   割り込みハンドラを設定する
   ブートセクタを読み最初の256バイトを0C000Hに転送する
   if ブート不可能
           DISK BASICを起動する
   0C01EHをキャリーフラグをセットして呼ぶ

 リスト2.3の6行目でallocされるメモリが、FATに必要とされるより1バイト多く割り当てられていることに注意して下さい。FATの先頭の1バイト前はメモリ内のFATとディスク上のFATが一致しているかどうかのフラグです。ディスク上のFATがまだメモリ内に読み出されていないときには255が、メモリ内のFATのみを変更して、まだディスクに書き出していないときには1が、一致しているときには0が書かれています。

 ディスク環境では全てのページのRAMのスロットアドレスがページ0から順に0F341H、0F342H、0F343H、0F344Hに格納されます。ページ2、3のRAMはMAIN ROMによって既に捜されていますから、それをスロットアドレスに変換して格納します。ページ0、1のRAMはマスターカートリッジが捜します。

 ページ0のRAMは全てのスロットに対して、

0010Hから0001Hまで1バイトずつ下位アドレス方向に
0410Hから0401Hまで1バイトずつ下位アドレス方向に
                    :
                    :
3C10Hから3C01Hまで1バイトずつ下位アドレス方向に

 ページ1のRAMは全てのスロットに対して、

4010Hから4001Hまで1バイトずつ下位アドレス方向に
4410Hから4401Hまで1バイトずつ下位アドレス方向に
                    :
                    :
7C10Hから7C01Hまで1バイトずつ下位アドレス方向に

の順でチェックされます。これも、MAIN ROMでのチェックと同様、元の内容を破壊することはありません。1Kバイトおきに15バイトだけがチェックされることに注意して下さい。RAMが実装されていないと判断された時点でそのスロットに関するチェックは終了し、16Kフルに実装されているスロットが見つかった時点で全てのチェックが終了します。

INITエントリおよびマスターカートリッジによる初期化が終了した時点で、RAMの内容は以下のようになっています。ここではディスクカートリッジが2つあって、最初のカートリッジは2台、次のカートリッジは1台のディスクをサポートしているとします。


図2.1 マスターカートリッジ初期化終了時のワークエリア

 【HIMSAV(0F349H)】はディスクシステムの核(カーネル)が動作するのに最低限必要なエリアの底へのポインタです。【$SECBUF(0F34DH)】、【$BUFFER(0F34FH)】、【$DIRBUF(0F351H)】は3種類のセクタバッファに対するポインタです。