S-OSねちねち入門

筑紫高宏
 
 ここからは、S-OSに関する入門を行っていきます。入門といっても、機種ごとの遠い,ふだんは気づかない細かい仕様の間違いなど,結構マニアックな内容を中心に進めていきます。初心者の方は,S-OS“SWORD"での礼儀作法を学ぶ,といった心構えで読み進めてください。
 

★S-OSのキャラクタ

 S-OS“SWORD"の使用するANK文字は,通常,MS-DOSなどで使用されるキャラクタと異なる部分があります。特に,重要なコントロールコードの動作などが異なっているため,テキストのやりとりを行うためには,コード変換をしてやる必要があります。原因は,シャープが8ビット機で,一部独自のキャラクタ(コントロールコード)を使用していて,S-OS“SWORD"は,その規格にかなり合わせたためです(表1。通常のものと,S-OS“SWORD"のものです。表示に重要な,主なコンロールコードも,一部記入しであります)。
 まず,「通常」のキャラクタについて説明します。これは,JISに規定されているのと,ほぼ同じものです。このJISのANK文字も,実は,正式なASCII文字と一部異なるようです。主なものは「¥」記号で,ASCII文字では,「\」です。7EHの「~」は,正式な文字は知りませんが,機種により,「 ̄」であったり,「〜」であったり,「 ̄」の位置に「~」があったりするようです。「¥」のような,日本でしか使わない(日本でもあまり使わない)コードは,カナの位置(A0Hなど)に定義するか,グラフィック文字にしてくれたほうがよかったでしょう。
 それでは,S-OS“SWORD"のキャラクタについて説明します。表1のキャラクタは,通常のS-OS“SWORD"マシンが持っている文字セットで,一部マシンは持っていない文字もあります。
 たとえば,MZ-80Kシリーズは小文字を持っていません(小文字は,大文字に変換されて表示されます)。カナの「ー(長音記号)」がない機種もあります。「ー」は,「−(マイナス)」を使うようにと,Oh!X(MZ)のはうから指示があったと思いますが,テキスト変換などで障害になるため,やはり「ー」の代わりに「−(マイナス)」の使用をすることは,避けたほうが無難でしょう。さらに「^」の文字が,「↑」と表示される機種もありました。
 あと持っていない可能性があるキャラクタは,「_」「|」「〜」「π」「・(中点)」などです。特徴的なキャラクタとして7BHの文字「■」,7DHの文字,チェッカー「□」があります(漢字にも対応パターンがありません)。これらの記号は,ゲームなどの表現に効果的ですが,キャラクタ番号が重なっている「{」と「}」の文字が使用できないため,言語を使用するときに,表示が不自然になったりします(区別はできるので致命的ではありませんが)。また,中括弧「{」「}」の代わりに大括弧「[」「]」を使用して問題を回避していたものもありました。
 
表1 キャラクタコードの違い
 
 
 次に,漢字の問題について説明します。漢字は,テキストファイルでは,JISコード(21H〜7EHのキャラクタを2つ組み合わせて表現)をシフトJISという形式に変換して,格納しであります。グラフィック文字だった部分(81H~9FH,E0H~EFH)を,シフトJISの第1バイトとして,次に統く1バイト(40H~7EH,80H~FCH)と組み合わせることにより表示系が漢字とみなすわけです。
 しかし,シャープのX1turboのBIOS,X68000の漢字認識には問題があり,たとえば,81H+0DHなどの,漢字の第1バイト+漢字の第2バイトにない文字(例では,改行コード)の組み合わせを,強引に「※」という文字に変換してしまいます。
 よって,従来のANK文字を対象としたキャラクタをダンプするプログラムでは,正しく改行できずに行と行がつながってしまう場合があります。これを遊けるには,行の最後に,空白キャラなどをくっつけて表示しないといけません(81H+20H+0DHなどとすれば,20Hが犠牲になって,ODHが正しく動作できます)。X68000では,改善してほしかったところです。
 今度は,S-OS“SWORD"と通常のコントロールコードなどの違い,および,変換,共通化の方法について説明します。
 最も重要な部類に属する改行についてですが,通常テキストファイルでは,0DH+0AHとなっていますが,S-OS“SWORD"の仕様では,0DHのみとなっています。そのため,相互にテキストを表示しようとすると,一般的に正しく表示されません。しかし,互換の方法はあります。0DHを改行コードとみなして,0AHを無視するのです。これなら,0DH改行であろうと,0DH+0AH改行であろうと,正しく改行してくれます。
 次にテキストの終端のコードです。一般的には,^Z(1AH)ですが,S-OS“SWORD"では,00Hとなっています。これも,アプリケーション(アセンブラ)などで,どちらのコードでも終端とみなせば,問題ありません。
 BREAK処理です。一般的には,^C(03H)ですが,S-OS"SWORD"では,ESC(1BH)となっています。よって,共通性がありませんが,これも,システムやアプリケーションのほうで,両方BREAKとみなせば,共通化できます。
 通常,7EHは,デリート処理になっていますが,S-OS“SWORD"では「π」となっています。よって,「π」は,積極的には使用しないほうがいいでしょう。もし,共通のキャラクタをダンプするプログラムを作る場合,7EHは,「.(ピリオド)」やスペースに変換して表示すれば問題ありません。
 タブについては,S-OS“SWORD"では標準でサポートしていません。一応,いくつかのアプリケーションではタブコードをサポートしています。しかし,それらはアプリケーションがテキストを表示,または取り込む段階で,タブコードを判別し,スペースへ強制的に変換するという強引な手段で実現されています。とはいえ,これぐらいはシステムでサポートしてほしかったところです。
 結果的に,S-OS“SWORD"でテキストの世界は,外部に閉じているといえます。しかし,いままで説明してきたことを,しっかりシステムやアプリケーション,ユーザーが対処してやれば,各種のファイルとやりとりできるようになります。さらに,システムが対応すれば,従来の形式との共存もできるようになるでしょう。
 

★画面構成

 S-OS“SWORD"でサポートしている画面構成は,
1) 40桁×25行
2) 80桁×25行
以上の2種類を基本としています。
 主にゲーム用として,40桁×25行を多くのシステムで表示できます。ちなみに,一部機種では,25行表示を無理やり行う場合もあります。ゲーム用の40桁×25行では,きっちり40桁x25行を表示する必要があるアプリケーションがありますが,それ以外の画面モードでは,広ければ広いほどいいと思います。
 

★画面

 S-OS“SWORD"では,ワークエリアから画面の広さを知ることができるようになっています。これは,S-OS“SWORD"の優れている点です。このため,エディタなどで,どんな桁,行を表示しでもへっちゃらです。この機能のないDOS用のアプリケーションでは,暗黙で了解の特定の桁数行数を念頭においてプログラムされていたり,ユーザーがなんらかの形で指定したり,機種固有のワークを参照したりしなくてはなりませんでした。
 表示桁数に関係するワークエリア,システムサブルーチンは次のとおりです。
●#WIDTH(1F5CH,1バイト)
 参照のみです。現在の表示桁数が入っています。
●#MAXLN(1F58H,1バイト)
 参照のみです。現在の表示行数が入っています。桁モードの変更も可能です。
●#WIDCH(2030H)
 仕様では,Accで指定して,40以下なら40桁,41以上なら80桁となっていますが,自由桁拡張のため,
「40桁なら40,80桁なら80,最大桁なら255を指定」
このような,新しい定義を提案したいと思います。
 ちなみにS-OS“SWORD"システムを作る場合,DOSモジュールが,#WIDCHで,Cyフラグのクリアを期待しています。必ず,Cyフラグをクリアして戻るようにしてください。また,表示桁数は,指定したあとワークで確認してください(指定した桁数に対応できない機種が存在するため)。
 ちなみに,S-OS“SWORD"には,表示行数を指定するルーチンがありません。
 

★カーソル

 位置の移動も,参照も可能です。
●#CSR(2018H)
 カーソル位置を参照します。#XYADR(1F78H,2バイト)による参照は禁止されています。
●#LOC(201EH)
 カーソルを移動します。#XYADR(lF78H,2バイト)による書き換えも禁止されています。標準X1用S-OS“SWORD"では,不正な値かどうかをチェックして,不当な値なら,Cyフラグセットでリターンします。
 仕様ではAFレジスタを破壊する,となっていますが,一部のアプリケーションでは,Accの保存を期待しているものがあります。S-OS“SWORD"システムを作る場合,Accを保存しないと,正常に動作しないアプリケーションが出てくる場合があります。注意してください。
 また,指定座標から文字を読み取る#SCRN(201BH)というルーチンがあります。お手軽ですが,機種によっては表示系に負担がかかり,処理に時間を必要とする場合があります。党えておいてください。
 

★MAGIC

 S-OS“SWORD"上から,MAGICを使用する際の手続きは,あまり厳密に設定されていません。基本的にMAGICは,S-OS“SWORD"用のグラフィックパッケージではないので当たり前かもしれませんが。それはtもかく,S-OS“SWORD"用に用意されているのは,MAGICの初期化のみです。そのため,トラブルが発生する可能性があります。S-OS“SWORD"でMAGICを使用する場合,最初にAF00Hを呼び出して初期化します。
問題1)MAGICの動く画面モード
 機種によっては,特定の桁数でしか動かないのに,ある機種ではすべての桁数で動いてしまうようです。よって,ある機種で動いても,ほかの機種では異常な表示になったりする場合があるようです。X1では,MAGICは,80桁モードのみ正しく動作します。MZ-1500では,文字画面は40桁モードしかありません。ここらへんの配慮が必要だと思います。
問題2)グラフィックの表示
 文字のみの画面のとき,通常,グラフィックの内容は不定と考えられます。そして,グラフィックの表示がOFFの状態だと考えられます。ところが,S-OS“SWORD"上から,グラフィックの表示のON/OFFを制御するルーチンがありません。初期イヒルーチンだけはあるので,一度呼ぶと,表示しっぱなしという意味でしょうか。
問題3)プライオリティ
 文字表示とグラフィック表示の優先度の規定がありません。システムによっては,文字のみ,グラフィックのみ,文字+グラフィックと,3つのパターンが考えられます。そして,いくつかのパターンができる機種と,そうでない機種があるはずです。さらに,文字との重ね合わせも問題です。要するに,文字が優先か,グラフィックが優先かということです。このへんも細かい規定がありません。一般的には,背景が黒(透明)で,文字の優先度が高くなっています。
問題4)MAGICの切り放し
 たいていの場合,問題になりませんが,MAGICの作り方によっては,問題になる可能性があります。ファイルのアクセスのオープンとクローズのようなものです。一般的に,初期化があれば,終了処理も必要と考えられます。先ほどもいいましたが,使用したらそれっきりになってしまうからです。画面比率モニタにより異なります。MAGICの横640×縦200ドットの場合,ドットの縦横比率は,40:91と,1:2の2タイプあるようです。テレビに映すときは,前者です。
 

★メモリ

 ユーザーが使用できる上限を知る方法として,次のワークが用意されています。
●#MEMAX(1F6AH,2バイト)
 仕様では,「メモリの上限」となっています。X1用標準S-OS“SWORD"では,最終アドレス+1になっていました。この「+1」があるかないかで違ってくることがあるので,メモリの上限は次のように解釈するといいでしょう。
「S-OS“SWORD"で使用できるメモリの最終アドレス+1」
 さらに,#MEMAXの値は,解釈の違いや,この値をチェックするルーチンの性格から,〜FFFFHまでのつもりの0000Hでは,トラブルが発生する可能性があります(7FFFHまで使用できるかをチェックする目的で,FF00H~8000HとするとCyフラグが立たないのでOKですが,0000H~8000HではCyフラグが立ってしまい,使用できないと判断されます)。よって,#MEMAXの値は最大FFFFHで0000Hは使用しないほうがいいと思います。
 一般的に,どの機種でも使用できるエリアは,3000H〜CFFFHくらいです。FEFFHまでフルに使用するプログラムだと,実質,X1専用となってしまいます。
 

★特殊ワーク

 これもS-OS“SWORD"のよい点です。プログラム用としては使えないメモリを,ワーク用などに使おうというアイデアです。特殊ワークはRAM上に用意されているので,高速にアクセスができます(ちなみに,ディスク上のイメージでも可能のはずです)。
●#WKSIZ(1F68H,2バイト)
 特殊ワークのない機種では,0000Hとなります。最大で、FFFFHです。よって,64K-1バイトまでしか活用できません。ちなみに,特殊ワークの大きさを3~4バイトで表現していたなら,16M-1バイトや,4T-1バイトまで対応できたでしょう。
 特殊ワークは有用ですが,使用する側の配慮が足りないと,いくつか問題が発生する場合があります。
問題1)特殊ワークの存在を期待
 いくつかのアプリケーションでは,特殊ワークがないと動かないものがあります。本来,プログラム用に使えないRAMを有効利用するための特殊ワークなので,プログラム用メモリを削って,特殊ワークを確保するのは,本末転倒でしょう。
問題2)特殊ワークの特定サイズを期待
 これも,前述の問題と同じです。ある特定の大きさがないと,正常に副作しないアプリケーションが存在します。当然,特殊ワークのサイズをチェックせずにアクセスするアプリケーションも存在します。
 一般的なS-OS“SWORD"では,アドレスが不正かどうかのチェックを行っていません。機種によっては,システムI/Oにまでアクセスし,暴走する可能性もあるので,特殊ワークを使用する場合は,必ずサイズをチェックしてください。
問題3)特殊ワークの特定初期状態を期待
 いくつかのアプリケーションでは,特殊ワークがクリアしであることなどを期待しています。特殊ワークの内容が不定だと,誤動作するものがあります。特殊ワークの特定の初期状態を期待しないでください。
 今回は,特殊ワークの初期状態が不定だと誤動作するアプリケーションを正常に動かすために,特殊ワークをクリアするプログラムCLRWK.SOSを作りました。ちなみに,最初に発表させてもらったMSX用S-OS“SWORD"では,起動時に特殊ワークをクリアしていました。しかし,ver.3.0では,S-OS“SWORD"自体の省メモリのためもあり,この機能を外し,プログラムのほうで対応しています。
 特殊ワークをアクセスするルーチンとして,
  #POKE(1F9AH)
  #PEEK(1F94H)
  #POKE@(1F97H)
  #PEEK@(1F91H)
が用意されています。なお#POKEは,破壊レジスタがないことになっていますが,ほとんどのS-OS“SWORD"では,フラグを破壊します。注意してください。
 いくつかのアプリケーションでは,#POKE@と#PEEK@を呼び出したあと,Cyフラグクリアを期待しているので,S-OS“SWORD"を作る場合は,Cyフラグをクリアするようにしてください。
 特殊ワークのルーチンは,もう少し進んで,ファイルハンドルのようなアクセスが可能だとよかったでしょう。アドレスを毎回指定するのは,かったるいので,オートカウントアップがあるとさらに便利です。
 

★プリンタ

 伝統的にシャープ系のプリンタ関係のシステムには,裸データを送ることができるというすぐれた特性がありました。X68000では,“LPT"というファイルでプリンタへ,コード変換されないデータを送ることが可能です(通常,プリンタへコードを送る場合,システムが,漢字をプリンタが受け取れるようにコード変換したりします。そのため,任意のバイナリデータをプリンタへ送りにくいのです)。このため,ビットイメージが簡単に送れ,プリンタを細かく制御することができます。
 しかし,残念ながらS-OS"SWORD"には,そのようなルーチンがありません。どちらかといえば,プリンタヘデータ出力したいときに,X68000のように“LPT"というファイルで送れたほうが,無駄なファンクションがなくていいです。
 ちなみにシャープ系のプリンタシステム関係は,タイムアウトというじゃまっけな仕様になっています(プリンタ側がエラーを起こしたとき,一定時間たつとプリントアウトが中断されるシステム)。そのためアセンブルしたリストをプリントアウト中に,紙切れを起こし,取り替えようとしている問に,タイムアウトでお流れになり,最初からもう一度打ち出し直しということが,何度かありました。
 また,S-OS“SWORD"には,画面への出力をプリンタへも出力(画面+プリンタ)できるようになっています。この機能があると便利なこともあるのですが,はっきりいって必要ありません。これは,表示系にプリンタルーチンを割り込ませる必要もあるので,表示速度も低下します。僕自身,プリンタへ出力する場合は,ファイルを経由しています。
 現在,プリンタへの出力モードかどうかは,#LPSW(1F7CH,1バイト)によって知ることができます。S-OS“SWORD"の正式な仕様には,「フラグ」としかありません。そのため,プリンタへの出力モードの切り替えに,#LPSWを直接書き換えるアプリケーションが存在します。
 しかし,#LPTON(1FD9H),#LPTOF(1FD6H)というルーチンで,プリンタへの出力モードを切り替えることができるようになっています。なるべくなら,これらのルーチンを使い,#LPSWを直接書き換えないでください。
 

★表示ルーチン

 表示関係で必要なのは,#PRINT(1FF4H)と#MSX(1FE5H)で,そのほかのルーチンは,ほとんど不要だと思います。特に,#PRNTS(1FF1H)などは,#PRINTで実現できるため意味がありません。
 #MPRNT(1FE2H)は,「AF,DEレジスタが破壊される」という仕様になっています。しかし,一部のアプリケーションでは,DEレジスタの保存を期待しています。問題が起きそうな気がするのですが,多くのS-OS“SWORD"では,DEレジスタを保存しているので,いままで表面化していないだけです。アプリケーションを制作するときには,トラブル回避のためDEレジスタを保存するようにしてください。
 #TAB(1FDFH)の仕様では,「Bレジスタの値とカーソルX座標の差だけスペースを表示する」となっています。ところが,カーソルのX座標は,40桁モードで0〜39,80桁モードで0〜79となり,表示する行が長い場合,途中て改行すると期待どおりのスペースを表示してくれない可能性があります(桁モードに依存する部分があるためです)。ここは,桁モードに依存しないように,「X座標」を「論理桁位置」に変えておきたいところです。
 #PRCNT(1F7AH,2バイト)は,「改行してからの表示文字数を,格納してあるアドレスを示している」という仕様になっています。
 しかし,この仕様説明だけでは,不明瞭な点も多いと思います。たとえば,行の途中でコントロールコードがきたらどうなるのでしょうか。画面ホーム位置移動とか,カーソル移動,TAB,エスケープシーケンスによる画面クリアなども同様です。利点が少ないうえ,表示速度がかなり遅くなるので,必要のないワークかもしれません。
 そして,#MSG(1FE5H)と#MSX(1FE2H)では,0DHや00Hまで表示するとなっていますが,実際には,0DHや00Hは表示しません。
 

★キー入力ルーチン

 S-OS“SWORD"の文字列入力について説明します。
 MS-DOSのようなラインではなくて,画面上をカーソルで,自由に移動できます。そして,任意の位置で,リターンキーを押すと,そのときカーソルがある論理行が,論理行末のスペースを省いた状態で,ごっそり,文字列の格納バッファに入力されます。S-OS“SWORD"での一般的な論理行は,処理の簡略化のため,画面の桁数までに制限されています。よって,X1用S-OS“SWORD"などでは,80桁モードの場合,最大で80文字まで入力されます。
 文字列入力バッファには,リターンキーのコードである,0DHは格納されません。文字列の最後には,必ず00Hが付加されます。また,途中で,入力を中断した場合(SHIFT+BREAK,ESC,Cなどを入力した場合),バッファには,「1BH,00H」が格納されます。
 S-OS“SWORD"を作る場合の文字列入力に関して,注意する点があります。X1用S-OS“SWORD"では,エンドコードの00Hから,表示桁数+1バイト目まで,00Hでクリアされています。いくつかのアプリケーション(ディスクモジユールも)では,このことを利用,あるいは期待して,エンドコードの00H以降も00Hでクリアしていないと,誤動作する場合があります。
 さらに,一部のアプリケーションが,文字列入力バッファを128バイト程度のワークとみなして使用しているので,十分な大きさの文字列入力バッファを確保する必要があります。
 また,文字列入力に関して,アプリケーション側が注意する点があります。システムの文字列入力バッファを使う場合は,文字列入力ルーチンに対して十分な大きさが確保されているはずですが,アプリケーション側が独自に文字列入力バッファを確保する場合は,大きさに注意が必要です。たとえば,X1用S-OS“SWORD"では,40桁モードの場合には41バイト,80桁モードの場合には81バイトが書き換えられます。
 次にパッチファイルを使用する場合についてです。RUN&SUBMIT,ディスクモジュール,ディスクI/Oには問題があり,ディスクをアクセスすると,裏レジスタを破壊しまくります。よって,パッチファイルを使用する可能性がある場合,S-OS“SWORD"の文字入力ルーチンでも,裏レジスタの保存を期待しないでください。
 あと,一般のS-OS“SWORD"の16進入カルーチンでは,小文字を受けつけないようです。これからS-OS“SWORD"を作る人は小文字も受けつけるようにしてください。
 

★ディスクのフォーマット

 S-OS“SWORD"のディスクは,X1の2Dに準拠しています。このフォーマットは,次のような弱点(特徴)をもっています。
1)フォーマットがマイナー(X1とS-OSだけ)
2)ファイルの大きさが64Kバイトに制限されている
3)タイムスタンプ(S-OS“SWORD"は非サポート)がいいかげん
 いちばん痛いのが,64Kバイト制限です。せめてもう1バイトファイルサイズエリアがあれば……。そしてタイムスタンプですが,規格のツメが甘いので,絶対的ではありません。同じ「8時13分」でも,どこの国かによって正確な時刻と食い違いますし,国情報も記録されないので,変換できない場合が発生すると思います。というわけで,これから,新規格のパソコンやDOSを作る場合には,内部的にはグリニッジ標準時にするのが理想かもしれません。ユーザーに知らせるときに,ローカル時刻に変換すればいいだけですから。
 さて,具体的なフォーマットを説明します。まず,物理的なフォーマットです。
1)1セクタ=256バイト
2)1トラック=16セクタ
3)片面=40トラック
4)面数=2つ
 つまり,ディスク1枚で320Kバイトになります。そしてS-OS“SWORD"上のファイルは,クラスタという単位で管理されます。このクラスタは,2Dの場合,1トラックと一致しますので,1枚で80クラスタということになります。なお1トラックは4Kバイトです。つまり1バイトのファイルでも,ディスクを4Kバイト消費します。最初の2つのクラスタは,ディスクの管理のために使用されるので,実際にユーザーが使用できるのは,78クラスタとなります。
 ディスクを扱いやすくするために,セクタに,順に番号を与えて管理しています。サイド0の最初のセクタがレコード0,最後のセクタがレコード15,次はサイド1に移って,最初のセクタがレコード16,最後のセクタがレコード31というふうに,面を交互にいききします。レコードは,0から1279まで存在します。
 最初の2つのクラスタ(レコード0〜31)は,ディスク管理に使用されます。内容は,FAT(ファイルアロケーションテーブル)と,ディレクトリです。ディレクトリには,ファイル名や,ファイルの開始クラスタ番号が記録されています。FATには,クラスタのチェイン情報が記録されています。
 ディレクトリには,レコード16〜31の4Kバイトが使用されます。1つのファイルの情報に32バイトが割り当てられるので,128個分ありますが,78クラスタしか余ってないので,最大78個のファイルまで登録できます。
 ディレクトリの32バイトの内容は表2のとおりです。
 
表2 ディレクトリのデータ内容
+0 ファイル属性
+1~+13 プライマリ名
+14~+16 拡張子
+17 パスワード
+18~+19 サイズ
+20~+21 先頭アドレス
+22~+23 実行アドレス
+24 年の下位2桁
+25 月,曜日
+26
+27 時間
+28
+29 00H
+30 先頭クラスタ
+31 00H
 

★ファイル属性

 01Hがバイナリファイルで,04HがASCIIファイルです。S-OS“SWORD"では,ASCIIファイルはディレクトリの「サイズ」の大きさとなりますが,X1では,FATのチェインが続く限りとなります。つまり,原型のX1フォー7ットでは,ASCIIファイルは,ファイルサイズに制限がなく,256バイト単位となります。
 ビット6をオンすると,プロテクトがかかり,ファイルを消去,改編できなくなります。ディレクトリを取ったとき,「*」がついた状態です。たとえば,バイナリファイルでは,01Hを41Hにすることで,プロテクトがかかります。もちろん,ビット6をオフすると,ファイルの消去や改編が可能に戻ります。
 前回の「S-OSのキャラクタ」で書いたとおり,S-OS“SWORO"では,文字とコントロールコードの体系が,一般のものやX1のものと一部異なります。したがって,ASCIIファイルの中身は,X1と完全な互換性がありません。改行コードはX1と同じですが,テキストのエンドコードが,X1では1AH,S-OS“SWORD"では00Hとなっています。
 

★プライマリ名と拡張子

 プライマリ名は,13文字まで作成可能です。拡張子は3文字までです。余りの部分は,MS-DOSと同じく,スペースで埋められます。X1やS-OS“SWORO"の一般的なシステムでは,小文字と大文字を区別します。しかし,INTEGRAL-X1や,Human68kでは,MS-OOSと同じく,小文字と大文字を区別しません。
 一般のDOSでは,ファイル名の途中のスペースを許していませんが,X1やS-OS“SWORO"では,ファイル名の途中にスペースを混入することが可能です。しかし,ファイル名の互換性のため,一般のDOSに比べて,特殊なファイル名は作らないほうがいいと思います。
 

★パスワード

 X1では,ファイルのパスワードをかけることができますが,S-OS“SWORO"では,この機能は使用しません。よって,必ず,パスワードをかけない状態の「20H」にしてください。サイズ,先頭アドレス,実行アドレスインテル式で,下位,上位の順にアドレスが格納されます。「サイズ」を「0000H」にすると,ファイルの大きさが64Kバイトとなる場合があります。一般のDOSでは,サイズをゼロにすると,実際にも,ファイルのサイズがゼロになり,意味が異なってくるので,注意してください。
 

★タイムスタンプ

 S-OS“SWORO"では使用しませんので,全部ゼロにしてください。しかし,X1と同じようにタイムスタンプをサポートしても,まったく問題ありません。
 一応,解説します。X1では,一部を除いてBCDコードとなっています。ただし,月と曜日は,4ビットずつのバイナリです。月は1〜12で,曜日は日曜から始まってO〜6です。1995年2月14日火曜日,午前0時30分なら,95 22 14 00 30 となります。MS-DOSでは,2秒単位まで記録されますが,X1では分単位までです。
 

★先頭クラスタ

 存在するファイルの先頭のクラスタの番号が記録されてます。ここと,FATにより,ディスク上のどのクラスタに,どういう順番でファイルが存在するかがわかります。クラスタは,0〜1をディスクの管理に使用しているので,2〜79が使用可能です。
 ディレクトリ領域は,最初,FFHで埋めつくされています。そして,ファイルを消去すると,ディレクトリ領域の該当する32バイトの先頭部分(ファイル脳性の部分)に00Hが書き込まれます(もちろん,そのファイルが使用していたクラスタも開放されます)。よって,ファイル属性の部分がFFHなら,それ以降の領域は,FATが初期化されてから,一度も使用されたことがないということになります。
 ここでFATについて解説します。
 FATには,レコード14が使用されます。FATの初期状態は,表3のようになっています。
 2Dで使用するのは,レコード14の最初から半分です。後半部分(ちなみに,X1フォーマットの2DDでは意味があります)は,00Hで埋めておきます。
 1バイトが1クラスタにあたり,2Dでは80クラスタあり,最初の2つはディスク管理に使用するので,ユーザーがファイル作成可能なのは,クラスタ2〜79(16進数で02H〜4FH)です。
 FATの+00H〜+7FHの位置が,クラスタ00H〜7FHに対応しています。
 FATの数値は,以下のようなな意味をもっています。
   00H
   01H〜7FH
   80H〜8FH
このクラスタは未使用
チェインしている次のクラスタ番号
クラスタでチェインが終わり,下位4ビット+1が,使用している最後のセクタ番号
 チェインしているクラスタ番号は,01H〜7FHまでの値をとることができます。このことから,FATの構造は,512Kバイトまで対応しています。実際には,2Dは320Kバイトなので,01H〜4FHまでの値が使用されます。X1turboでは,2DDや2HDの容量に対応するため,無理にこの形式を拡張し,少し面倒な構造になっています。
 FATの+50H〜+7FHの部分は,未使用とみなされないために,8FHで埋めておきます。ファイルをコピーする場合は,X1とS-OS“SWORD"の両方に対応するため,FATのほうを見てください(X1形式のASCIIファイルでは,ファイルサイズが意味をもたないため)。
 
表3 FATの初期状態
    +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +A +B +C +D +E +F
00 : 01 8F 00 00 00 00 00 00 00 00 00 00 00 00 00 00
10 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
20 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
30 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
40 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
50 : 8F 8F 8F 8F 8F 8F 8F 8F 8F 8F 8F 8F 8F 8F 8F 8F
60 : 8F 8F 8F 8F 8F 8F 8F 8F 8F 8F 8F 8F 8F 8F 8F 8F
70 : 8F 8F 8F 8F 8F 8F 8F 8F 8F 8F 8F 8F 8F 8F 8F 8F
80 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
90 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
A0 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
B0 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
C0 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
D0 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
E0 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
F0 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
 

★ディスクフォーマット追加事項

 ちょっと余談になりますが,X1フォーマットのディスクのディレクトリ部分について,もう少し解説します。S-OS“SWORD"のみを使用しているときには参照する必要はありませんが,X1のディスクを操作する場合に参考にしてください。以下の情報は,X1turboZのマニュアルから抜粋+αしたものです。
●ファイル属性(+0)
 ビット0 Bin形式ファイル(バイナリファイル)
 ビット1 Bas形式ファイル(BASICの中間言語のテキスト)
 ビット2 Asc形式ファイル(ASCIIファイル, そして64Kバイト以上のバイナリファイル)
 ビット3 未使用 (0を書きます)
 ビット4 1で不可視になります。
 ビット5 1でリードアフターライトON
 ビット6 1でライトプロテクト
 ビット7 1で下位ディレクトリ
 属性の各ビットは,矛盾がない限り,複数指定可能です。ただし,通常,ビットO〜2は複数指定されません。複数指定すると,別の(未定義)ファイル形式ということになります。
 通常のバイナリファイルは,Bin形式ですが,64Kバイト以上のファイルだと,この形式で表現することができません。そのためAscファイル形式で、,中身はバイナリファイルという使い方もされます(ただし256バイト単位)。当然,ファイルサイズや先頭アドレスなどの情報は,意味をもたなくなります。
 なお,Asc形式ファイルのサイズですが,X1ではFATのみ意味をもちますが,S-OS“SWORD"ではBin形式ファイルと同じく,ディレクトリ上のサイズが有効となります。
 階層化ディレクトリですが,BASIC上からMKDIRすると,属性が「11000000B」になります。さらに,拡張子の部分が強制的に「DIR」となります。
 ビット5のリードアフターライトに関しては,勉強不足でわかりません。
●先頭クラスタ番号(+29〜+31)
  +29 上位
  +30 下位
  +31 中位
 ディスクのクラスタは4Kバイトなので,1バイトあれば,1Mバイトまで表現できます。ちなみに,2HDの場合は2バイトを使用します。3バイト用意してあるのは,256Mバイト以上の大容量デバイスを考慮したときのためでしょう。
 

★メモリマップ

 標準的なS-OS“SWORD"内部のメモリマップを紹介します。
 S-OSシステムの主な構造ですが,まずBIOSや各機種モニタが存在し,その呼び出しなどを共通化+αしたものが,初代S-OS“MACE"です。多くのマシンのS-OSシステムでは,0000H番地からBIOSやマシン語モニタが存在していて,そのすぐ後ろに付加する形で,基本的なサブルーチンの呼ぴ出しの橋渡しをするようになっていました。ファイル操作は,カセットテープのみ対応しています。
 S-OS“SWORD"へのバージョンアップは,主にディスクへの対応です。共通のディスク処理ルーチンと,原始的な機種依存のディスクI/Oルーチン(指定レコードを読み書きするだけ)が,完全に分離した形で制作されていたので,S-OS“MACE"への若干の手直しと,ディスクI/Oルーチンの制作だけで,各機種への移植を行うことができました。
 S-OS“SWORD"を制作する場合,特に共通ディスク処理ルーチンを使用する場合は,プログラムアドレスなどに制限が出てきます。もちろん,手間はかかりますが,襟準で用意されたものを使用しないことも可能です(要するにすべてを作り直せばいい)。その場合,アドレスの制約は若干減ります。ちなみに,S-OS“SWORD"システムが使用する0000H〜2FFFHのエリアには,空きエリアがほとんどない状況で,S-OS“SWORD"からのバージョンアップが行われなかった大きな理由のひとつでしょう。
 次に,メモリマップの内容を簡単に説明します(表3)。
 S-OS“SWORD"のメイン部は,0000H〜1CBFHにあります。BIOSを自作する場合でも,S-OS“SWORD"メイン部に使用できる領域は,7Kバイトほどです。
 RUN&SUBMITは,パッチファイルの実行などの機能を追加するパッケージです。次に位置するのが,S-OS“SWORD"のワークとジャンプテーブルです。通常のユーザーは,この部分を参照したり呼び出したりできます。
 共通DOSモジュールは,ディスクの入出力を行うルーチンの固まりです。
 ディスクI/Oルーチンは,DOSモジュールから呼び出されます。このルーチンを制作すれば,ディスクへの入出力が可能になります。一般的に,RAMディスクの処理ルーチン本体は,メモリの都合で2954H〜のエリアに配置されています。
 
表3 標準的なS-OS“SWORD"システムのメモリマップ
0000H   各機種BIOS
      またはマシン語モニタ (各機種依存)
      S-OS“SWORD" メイン部 (各機種依存)
  1CBFH  バグ回避用空き (各機種依存)
1CC0H 1F31H RUN&SUBMIT (各機種共通)
1F32H 1F5AH RUN&SUBMIT (空き)
1F5BH 1F81H S-OS“SWORD" ワーク
1F82H 1F8DH S-OS“SWORD" ワーク拡張用エリア
1F8EH 2038H S-OS“SWORD" ジャンプテーブル
2039H 204AH S-OS“SWORD" ジャンプテーブル拡張予約エリア
204BH 20FEH バッチ変数
20FFH     デバイス「E:」のクラスタ数
2100H 28CCH 共通DOSモジュール
28CDH 28FFH 共通DOSモジュール空き
2900H 2953H S-OS“SWORD" 内部ジャンプテーブル&ワーク
2954H 29FFH RAMディスクドライバ (各機種依存)
2A00H 2AFDH S-OS“SWORD" エラーメッセージ
2AFEH 2AFFH エラーメッセージ空き
2B00H 2BFFH ディスクI/Oルーチン (各機種依存)
2D00H 2DFFH バッチファイル用ディスクバッファ
2E00H 2EFFH ディスク入出力バッファ (FATバッファ)
2F00H 2FFFH ディスク入出力バッファ (データバッファ)
 

★ディスクI/O

 ディスクI/Oは,S-OS“SWORD"でディスクを操作するための各機種依存部分です。ここは,共通DOSモジュールより呼び出されます。ディスクI/Oの仕様は,正式に公開されてはいないため,ソースリストを解析した結果を示します。
 まず,ディスクI/Oのために用意されたエントリアドレスは,2B00H〜2B06Hの7バイトです。ディスクI/O本体は,2B07H〜2BFFHに置かれます。ちなみに,ディスクI/Oルーチンは,リードとライトのルーチンを共通化して作成し,動作時に自己書き替えを行うことにより,サイズのコンパクト化を図っている場合が多いようです。
 そして,RAMディスクのI/Oルーチンは,2B00H〜2B05Hのジャンプテーブルを乗っ取る形で動作します。このRAMディスクI/Oのためのルーチンは,だいたい空きエリアの2954H~29FFHに作成されています。
 そして,ディスクI/Oのエントリアドレスは,次のようになっています。
DREAD(2B00H) ディスク読み込み
DWR1TE(2B03H) ディスク書き込み
UNITNO(2B06H) ユニット番号(書き込みのみ)
 S-OS“SWORD"では,フロッピーディスクは,4台までつなげられます。ドライブ名は“A〜D",ユニット番号は0〜3に対応します。
 さらに,ドライブ名“E"がRAMディスクとなっていて,ユニット番号が4となります。ディスクI/Oを呼び出す場合,対象となるドライブを,2B06Hにユニット番号で指定することになります。
 なお,S-OS“SWORD"では,共通DOSモジュールのほうでも,ディスクI/Oでも,ベリファイを行っていません。
 次に,ディスクI/Oの基本ルーチンの仕様について説明します。
●DREAD(2B00H)
〈内容〉
ディスクからの読み込み
〈入力〉
HL←アドレス,DE←レコード番号,Acc←レコード数,[UNITNO]←ユニット番号
〈出力〉
Cy=0(Acc←0)なら成功,Cy=1(Acc←エラーコード)なら失敗
〈破壊〉
AF,AF'
●DWRITE(2B03H)
〈内容〉
ディスクへの書き込み
〈入力〉
HL←アドレス,DE←レコード番号,Acc←レコード数,[UNITNO]←ユニット番号
〈出力〉
Cy=0(Acc←0)なら成功,Cy=1(Acc←エラーコード)なら失敗
〈破壊〉
AF,AF'
 ちなみにこれらのルーチンは,S-OS“SWORD"のファンクションコールの#DRDSB(2000H)と#DWTSB(2003H)のメイン部分です。
 次にディスクI/O関係の問題点を説明します。
 まず,MZ-1500系統のディスクI/Oでは,割り込み禁止をしていないので,ディスクアクセス中に割り込みがかかった場合,エラーが発生する可能性があります。ただ,実際には,割り込みが使われないことが多いのでほとんど問題となっていません。しかし,S-OS“SWORD"上でオリジナルのプログラム(S-OS“SWORD"に依存しないもの)を組もうとしているときは,注意してください。
 そして,先ほど説明しましたが,ディスクI/OではAF'レジスタが破壊されます。さらに,それらを呼び出す共通DOSモジュールでも,AF'レジスタの保存を行っていません。したがって,ディスクをアクセスするルーチンを使用すると,AF'レジスタが破壊されてしまいます(仕様では保存されることになっている)。これは,バッチファイルを使用する場合にも当てはまります。つまり,ユーザーがディスクをアクセスするルーチンを使用する場合や,使用する可能性がある使い方をする場合,AF'レジスタは破壊されるとみなしてください。
 また,これからディスクI/Oを作成する場合は,仕様書どおりAF'レジスタを保存するようにしましょう。
 RAMディスクに関してですが,ETRK(20FFH)というS-OS“SWORD"の内部ワークに,RAMディスクのクラスタ数を格納してあります。これにより,RAMディスクの有無,サイズを知ることが可能です。
 おまけですが,X1用のS-OS“SWORD"では,ディスクのヘッドの移動速度を20msに設定してあります。しかし,内蔵ドライブは最高6msでもヘッドの移動が可能です。ということで,最高速に設定するための変更アドレスを書いておきます。ただし,ディスクのシーク音が気に入らない,ちよっとおかしいな?と思ったらすぐに戻しましょう。
2C21:1E→1C
2C98:02→00
 ちなみに,S-OS“SWORD"のディスクのデータバッファは,256バイトしか用意されていません。このためセクタの大きさが,512バイトや1024バイトのディスクを読もうとすると,ユーザーエリアに重なるため,暴走する可能性があるので注意してください。
 

★RUN&SUBMIT

 RUN&SUBMITは,バッチファイルを実行可能にする共通パッケージです。これは,1CC0H〜1F5AHに割り当てられています。#GETL(1FD3H)と#FLGET(2021H)を乗っ取ります。ついでに,DOSモジュールのコマンドも拡張します。拡張されるコマンドは以下の2つです。
●;
 ";"のある1行のコメントを表示します。MS-DOSのREMコマンドに相当するものです。
●P
 バッチファイル中にキー入力待ちを行います。なにかキーを押せば,バッチファイルの実行を再開します。ただし,1BHのキー(機種により,ESCやSHIFT+BREAKなど)を押すと,バッチファイルの実行を中断します。
●RUNコマンド
 RUN&SUBMITを組み込まない場合,ファイルの実行は,ロードコマンドでロードして,ジャンプコマンドで実行アドレスヘジャンプします。S-OS“SWORD"では,コマンドラインで入力されたコマンドの前にあるスペースを取り除いて,コマンドの解析を行いません。つまり,コマンドの前にスペースを掃入してしまうと,コマンドを受けつけなかったのです。RUN&SUBMITでは,この性質を逆手に取って,スペースのあとにファイル名を続けると,そのファイルを実行するようにしています。
 そしてアプリケーション側に,パラメータを渡すことも可能です。ファイル名のあとに":"をつけると,その次のアドレスをDEレジスタにセットして,アプリケーション側へ処理を移します。なにもパラメータがない場合には,DEレジスタに00Hが入っています。
 RUNコマンド(ファイルの自動実行)によりプログラムを実行し,終了した場合,再びRUN&SUBMIT側に制御が戻り,AFレジスタの内容を参照します。Cy=1ならエラーで,Accの内容がエラー番号となります。もし,Cy=1だったら,対応するエラーメッセージを表示します。よって,ユーザーがS-OS“SWORD"用プログラムを作成する場合,特に意図がなければ,Cy=O,Acc=Oにしてから,プログラムを終了するようにしてください(プログラムの最後に“SUBA"の1行を加えればOKです)。
●パッチファイル
 RUNコマンドで指定されたファイルがASCIIファイルなら,バッチファイル(S-OS“SWORD"では,キー入カルーチンを乗っ取り,ファイルにある文字列をキー入カルーチンに渡すようにしています)として実行されます。このパッチファイル読み込み用に,2D00H〜2DFFHが使用されています。
 パッチファイル中で“¥"(S-OS“SWORD"文字で"\")は,パッチ変数のために使用されます。"¥"という文字を使いたい場合は,"¥"を2重の"¥¥"にすると,l文字の"¥"とみなされます。
●パッチ変数
 MS-DOSなどにある,パッチ変数が使用可能になります。ただし,MS-DOSでは"%n"ですが,S-OS“SWORD"では,先ほどもいったように"¥n"です(S-OS“SWORD"では,キャラクタが一部違うので,実際の表示は"\n"などになります)。"n"の部分は数字で1〜9が指定可能です。1つの変数に20バイトが割り当てられ,19文字まで有効です。S-OS“SWORD"では,パッチ変数O番"¥0"を指定した場合ビープ音が鳴り,カーソル位置はそのままでユーザー側に制御が戻るようになっています。
 このパッチ変数ですが,コマンドラインで指定されたスペースで区切られたパラメータを,順番に1〜9と番号をつけてバッフアに格納しておき,バッチファイル中にパッチ変数がくると,パッチ番号が格納された文字列に置き換えられます。
 ちなみに,S-OS“SWORD"ではファイル名中にスペースを許している関係で,ファイル名(実行ファイル)とパラメータを":"で区切ってください。
 それでは,RUN&SUBMIT関係の問題点などを説明します。RUNコマンドを実行しようとした場合,ファイル先頭が3000Hで,かつ,ファイルの大きさが7Kバイト未満なら,3000H〜4BFFHのメモリの内容が,いったんRAMディスクの一部のエリアに待避されて,ファイルの実行後,元に戻されます。この待避用に使われるのが,RAMディスクのレコード0〜13,18〜31です。このうち,レコード18〜31は,ディレクトリエリアなので,16個より多くのファイルが存在していた場合,重複しているファイルが破壊されることになります。
 ただし,RAMディスクの大きさが68Kバイト以内なら,この問題は発生しません。
 もし,320KバイトのEMMなどを使用していて,16個以上にファイルを保存するつもりなら,以下の改造で,待避機能を潰し,問題を回避することが可能です。
1CFC:CD 15 1D→00 00 00
 そして,画面2行にまたがるバッチファイルは,誤動作します。これは,論理桁位置の代わりにX座標を参照しているためです。
 バッチファイル実行中は,S-OS“SWORD"ファンクションの#GETLや#FLGETで,AF'レジスタが破壊されることがあります(ディスクI/Oの関係上)。
 また,起動時に実行されるAUTOEXEC.BATは,ドライブAに固定されています。立ち上がったドライブをデフォルトドライブにできるS-OS“SWORD"でも,強制的にドライブAに読みにいきます。
 デフォルトドライブよりAUTOEXEC.BATを実行したい場合は,以下のアドレスを変更してくfごさい。
1F1A:'A:AUTOEXEC.BAT',00H→ 'AUTOEXEC.BAT',00H,00H,00H
 

★エラーコード

 S-OS“SWORD"のエラー番号と,メッセージの対応表を掲載します(表5)。メッセージは,2A00H〜2AFFHの共通DOSモジュールのソースに入っています。
 エラー0は,エラーなしという意味で,エラー15以上だとそのエラー番号,たとえば,エラー15の場合「Error $0F」と表示されます。
 
表5 エラーコード
1 Device I/O Error
2 Device Offline
3 Bad File Descripter
4 Write Protected
5 Bad Record
6 Bad File Mode
7 Bad Allocation Table
8 File Not Found
9 Device Full
10 File Already Exists
11 Reserved Feature
12 File Not Open
13 Syntax Error
14 Bad Data
15~ Error $??
 

★コマンドライン

 S-OS“SWORO"を立ち上げると,プロンプトの「#」記号が出て,コマンド入力待ちになります。この処理を行っているのが,共通DOSモジュールです。このとき使える内部コマンドを紹介します(dはデバイス名)。内部コマンドは,ほとんどが1文字(一部2文字)です。そして,コマンドのあとには,1文字以上のスペースを空けるのが望ましいとされています。
●L d:filename.ext
 L d:filename.ext:nnnn
 ファイルをロードします。
 16進4桁でアドレスを指定すると,そのアドレスから読み込みます。
●S d:filename.ext:xxxx:yyyy
 S d:filename.ext:xxxx:yyyy:zzzz
 メモリの内容をセーブします。
 アドレスは16進4桁で指定します。「XXXX」は先頭アドレス,「YYYY」は最終アドレス,「ZZZZ」は実行アドレスです。実行アドレスを省略すると,先頭アドレスが実行アドレスになります。
●K d:filename.ext
 指定したファイルを消去します。
●N d:filel.ext:file2.ext
 「filel.ext」を「file2.ext」にリネームします。
●ST d:filename.ext:P
 ST d:filename.ext:R
 ライトプロテクトの設定,解除を行います。パラメータに"P"を指定すると,ライトプロテクトがかかり,"R"を指定すると,ライトプロテクトを解除します。
●DV d:
 デフォルトデバイスを変更します。
 S-OS“SWORO"で,通常使用されるデバイスは,表3のとおりです。
●D
 ディレクトリを表示します。
●!
 ブートします。
●Jnnnn
 16進4桁「nnnn」で指定したアドレスをコールします。
 共通DOSモジュールの該当する処理ルーチンでは,DEレジスタを破壊してしまうので,パラメータを渡すことができません(このことは,深谷崇氏に教えていただきました)。パラメータを受け取ろうとすると,DEレジスタのアドレスが不定のため誤動作する可能性があります。以下の改造を行うと,"J"コマンドで,アプリケーションにパラメータを波すことができるようになります。
217B:EB 21 00 21 E3 EB E9 →E3 21 00 21 E3 E9 00
●M
 各機種のモニタをコールします。
 一般的なモニタでは,そのモニタの「R」コマンドなどで,呼び出したシステムに戻ってくることが可能ですが,一部の機種では戻る機能がありません。その場合は,S-OS“SWORD"の#COLD(1FFDH)か,#HOT(1FFAH)へジャンプしてください。
●W
 40桁モードと80桁モードを切り答えます。
 「W」コマンドが実行されたとき,80桁モードなら40桁に,40桁モード以外なら80桁に変更されます。
 
(C)1995 Takahiro Chikushi(original)
(C)1997 Junji Okazaki(edited)
(C)2024 Oh!Ishi,Nibbles Lab.(formatted)