「「「「     PC−1600Kの解析 その1       」」」」                            (C)1992 E.KAKO PC-1600Kでプログラミングするときに必要なIOCSですが、これを解析して 分かったことを書きます。 工学社の「PC−1600Kデータブック」にIOCSは解説されていますが ここに掲載されていないことが、解析によっていくつか明らかになりました。 −−− 1. IOCSのエントリについて −−− IOCSを使用する方法は、一般に、「 CALL エントリ・アドレス 」 です。データブックのP.15には表示関係(LCD)のIOCSが載ってい ます。これによると、「ANK1文字表示」というのは、0100Hというア ドレスということが分かります。 では、このIOCSの処理はどうなっているのか0100Hの内容を調べると 「0100H DF 00 80 ・・ ・・ ・・ 」となっているのが分かります。これを逆アセン ブルすると、DFHというのは「 RST 18H 」となります。その次の 2バイト00Hと80Hは、処理先が8000Hではないかと想像されていま した。 −−− 2. RST命令について −−− さて、このRST命令ですが、データブックP.144に「Z−80のRST 命令の使い方」というのが載っていますが、「RST 18H」について全く 説明されていませんので、解析した内容を以下に説明します。 「RST 18H」は2バイトのオペランドを取り、その値に従って4箇所の 本体ROMにバンクを切り替えて呼び出し、戻ってくるときにバンク状態を元 に戻し、RETします。 (P.10かP.180のメモリマップを参照) (1) 0000H〜3FFFHの場合 : バンク#0の0000H〜3FFFHのROMが呼ばれます。 (2) 4000H〜7FFFHの場合 : バンク#3の4000H〜7FFFHのROMが呼ばれます。 (3) 8000H〜BFFFHの場合 : バンク#6の8000H〜BFFFHのROMが呼ばれます。 (4) C000H〜FFFFHの場合 : バンク#0の4000H〜7FFFHのROMが呼ばれます。 (2)の場合のバンク#3は、さらに2つのバンクに分かれていて I/Oポート(3DH) のbit2でバンクされます。bit2=HI側のROMが呼び出され、これも戻ったときに バンク状態は元に戻されます。 注意しなければならないのは、IOCS実行後バンク復帰ルーチンへリターン するので、RST18Hを実行した場所には戻ってこないということです。で すから、戻るべきアドレスをスタックに積んでからRST18Hを実行するか、 RST18Hの書いてあるアドレスをCALLするかしなければなりません。 −−− 3. IOCSの内部処理について −−− 「CALL 0100H」とすると、バンク#6の8000HをCALLするのと同じ ことになりますが、バンクをわざわざ切り換えて保存をしなくてもすみます。 「ANK1文字表示」というのはバンク#6の8000H から始まるということです。 逆アセンブルしていくと、次のようになります。 8000H C3 2C 88 JP 882CH 882CH CD BB 00 CALL 00BBH 882FH CD 70 00 CALL 0070H 8832H CD 29 83 CALL 8329H 8835H C0 RET NZ 8836H D5 PUSH DE (以下省略) この「CALL 00BBH」と「CALL 0070H」というのはIOCS の動作には関係ないもので、これをこれからは「IOCSフック」と呼びます。 アドレス00BBHには、「CALL F09DH」と書かれています。本体 RAMのF09DHの内容を書き換えてやれば、ANK1文字表示のIOCS の本来の処理を横取りすることができます。(ただし、漢字1文字表示のIO CSの処理も同時に横取りすることになるので注意が必要です。) −−− 4. IOCSフックについて −−− 0070Hから「CALL F09DH」が25個並んでいます。 00BBHから「CALL F0A2H」が2個並んでいます。 00C1Hから「CALL F0A7H」が8個並んでいます。 F09DHをIOCSフックAと呼ぶことにします。 F0A2HをIOCSフックBと呼ぶことにします。 F0A7HをIOCSフックCと呼ぶことにします。 フックAは、以下の25種類のIOCSにフックする場合に用います。表示関 係全般の処理を横取りできます。 HOOKCALLアドレス IOCSの種類 0070H PRT ANK ANK1文字表示 0073H PRT KNJ 漢字1文字表示 0076H PRT ASTR ANK文字列表示 0079H CLS 画面のクリア 007CH RVSCHR 表示の一部を反転する 007FH CRSR STAT カーソル形状設定 0082H LINE 線を描く 0085H BOX 四角形を描く 0088H DOT SET 1ドット点灯/消灯/反転 008BH DOT READ 1ドットの状態を返す 008EH UPSCRL アップスクロール 0091H DWNSCRL ダウンスクロール 0094H SMBL READ シンボルの状態を返す 0097H SMBL SET シンボルの状態を設定する 009AH ERS STR 文字列の長さだけ空白を表示 009DH INS1LN 空白行を1行挿入する 00A0H ERS1LN 1行を空白にする 00A3H PRT GCH グラフィックカーソル位置から1文字表示 00A6H PRT GSTR グラフィックカーソル位置から文字列表示 00A9H PRT GPTN グラフィックカーソル位置にパターン表示 00ACH GPTN READ グラフィックカーソル位置のパターンを返す 00AFH 不明あるいは未使用 00B2H 不明あるいは未使用 00B5H PRT KSTR 漢字文字列表示 00B8H DSPCTR ディスプレイON/OFF フックBは、以下の2種類のIOCSにフックする場合に用います。1文字表 示処理を横取りできます。 HOOKCALLアドレス IOCSの種類 00BBH PRT ANK ANK1文字表示(P.15を参照) 00BEH PRT KNJ 漢字1文字表示 フックCは、以下の8種類のIOCSにフックします。キーボードからの入力 処理を横取りできます。 HOOKCALLアドレス IOCSの種類 00C1H KEYGET キーバッファリード(入力待ち) 00C4H KEYGETR キーバッファリード(待たない) 00C7H BREAKCHK ブレークキーを調べる 00CAH CURUDCHK ↑↓キーを調べる 00CDH KEYDIRECT キースキャンしキーコードを返す 00D0H OFFCHK OFFキーを調べる 00D3H KEYGETND バッファを調べる(非破壊) 00D6H BREAKRESET ブレークキーのラッチをクリア −−− 5. IOCSフックの利用について −−− 1つのフックに複数のIOCS処理が入ってきますので、処理を横取りすると きには、注意が必要です。 例として、フックBを書き換えて PRT ANKの処理を横取りする方法を以下に書 きます。 (例えば、キャラクタコード20H〜7FH に対してユーザー独自のフォ ントを表示させるという応用が考えられます。しかし、そのとき PRT KNJには 何も影響を及ぼさないようにしなければなりません。) フックBのF0A2Hには「 INC SP INC SP RET 」と書かれています。 これを「 JP C100H 」と書き換え、C100Hからプログラムを用意しま す。 (C100Hというアドレスは、自分で好きなところにプログラムを置 いてやれば別にどこのアドレスでも構わないですが、IOCS実行中はバンク が切り替わっていますので影響を受けないC000H以降が望ましいです。) C100Hに処理が移ったときのスタックの内容は以下のようになっています。 ( SP+00,+01 ) : 00BEH(IOCSフックCALLのアドレス+3) ( SP+02,+03 ) : 882FH(PRT ANKの中へのリターンアドレス) ( SP+04,+05 ) : 0AE4H(バンク復帰ルーチンへのリターンアドレス) ( SP+06,+07 ) : 元に戻すべきバンクの状態 ( SP+08,+09 ) : IOCSを呼びだしたところへのリターンアドレス ですから、SP+00,+01を調べて、それが00BEHという値であれば、 PRT ANK に相当の処理をする自作プログラムを実行し、そこから戻るときには 「 INC SP INC SP INC SP INC SP RET 」 とします。 SP+00,+01を調べて、00C1Hであれば、ROM内の PRT KNJの中 からフックしてきたということですので、これを正常に処理し復帰するために 「 INC SP INC SP RET 」 とします。 −−− 6. 未公開IOCSについて −−− IOCSのエントリについて「データブック」で調べてみると、アドレスが抜 けている部分が多くみられます。その部分には未公開のIOCSが存在します。 以下のものは私が内容を調べ、勝手に名前を付けたものです。 {1} LCD表示関係の未公開IOCS アドレス 名前 内容 0106H PRT ASTR0 PRT ASTRと同じ。文字列の終りは00H 入力:PRT ASTRを参照 0151H PRT GSTR0 PRT GSTRと同じ。文字列の終りは00H 入力:PRT GSTRを参照 0163H PRT KSTR0 PRT KSTRと同じ。文字列の終りは00H 入力:PRT KSTRを参照 0136H SETCG80 コード80H以降のキャラクタのCGを設定/初期化 入力:A = CGのバンク DE = CGのアドレス (DE=0000Hのとき初期化) (P.24参照) ただし、初期化の動作がおかしいのでDE=0000Hは使わないほうがよい。 020BH INITCG80 キャラクタコード80H以降のフォントのCGを初期化 入力:なし こちらは正常に動作しています。 010FH SELECTLCD LCDの種類を設定 ( ワークエリア F05DH(LCDWK1)のbit1を変更する ) 入力:A=0 ... 156x32dotのLCD(普通これになっている) A=1 ... 240x32dotのLCD 240x32のLCDが搭載されていないので、指定しても表示が乱れるだけで 何の意味もない。240x32の場合 ANKで40文字x4行、漢字で15文字x4行。 0208H CRSRBLINK カーソルを点滅させる         入力:なし 割り込み中で使われるのではないかと思われるが、詳しくは不明。 {2} BEEP関係の未公開IOCS アドレス 名前 内容 01C0H BINIT1 ブザーをBEEP有で初期化 入力:なし 01C3H BINIT2 ブザーを設定に従って初期化 入力:なし (BEEPの有/無についてはP.82を参照) {3} メモリ関係の未公開IOCS アドレス 名前 内容 01B1H BANKLDIR バンク切換&データ転送 (バンクを切り換えてからLDIRで転送し、バンクを戻す) 入力:B ... 切り換えるバンク状態(I/Oポート31H参照) C ... 転送するバイト数 HL ... 転送元アドレス DE ... 転送先アドレス まだ多くの未公開IOCSが残っています。解析中ですので追加情報がまだ出 てきます。続編としてまた記事にしたいと思います。 また、メモリマップを64KB全部にRAM配置してプログラムを動かす方法 についても解析ができていますのでそのうち記事にしたいと思います。 −−− 7. 使用上の注意と転載等の条件について −−− ここに今回書いたことは、参考文献の内容以外、加古英児が調べたものです。 この内容について、何らかの誤りが存在する可能性がありますので、注意して 使用してください。 この記事の転載等は、著作者の権利を侵害しないようにしてもらえば、あとは 自由にしてもらって結構です。