• ベストアンサー

peek()の機能が使えれば・・・

テキストモードで24×80のがその画面を準備し、"スペース"と"*"で画面上に図形を描き、どんな図形かを調べるプログラム http://www-itolab.ics.nitech.ac.jp/lecture/creport/enshu_kadai/practice5.html に置いてある"rec_angle.c"をUNIXで動くようにしたいのですが、できません。エラーの内容から A.1行目 #include "dos.h" B.3行目 #define VRAM 0xa000 C.148行目から193行目 IBM-PC用のcheck_point(),gotoxy(),cls()  D.195行目から225行目 PC98用のcheck_point(),gotoxy(),cls() 辺りが怪しいのです。実際にコンパイルするときはCとDのどちらかはコメントアウトしなければいけません。 上のURLではIBM用がコメント扱いになっています。(208行目の"/*"と219行目の"*/"は打ち間違いです。) そして方針としては (1)dos.h、int86、peekなどをUNIX上で使用できるような環境にする。 (2)IBM用の関数らを書き換える。 (3)PC98用の関数らを書き換える。 が考えられます。 自分としては(3)がいいと思っています。 203行目: dat=peek(VRAM,xy); 212行目: printf("\x1b{"); 223、4行目: printf("\x1b{"); printf("2J"); だけをUNIXで使えるものに置き換えればいいようなので。(自信がないですが) (1)、(2)については全くどうしていいか分かりません。 どのような方法でもいいのでUNIXで(それ難しい場合はせめてWINDOWSで)動くようにしたいのですが、どうかお助けください。どちらもGCCを使っています。

質問者が選んだベストアンサー

  • ベストアンサー
  • MovingWalk
  • ベストアンサー率43% (2233/5098)
回答No.2

基本的には、機種依存の次の3つの関数を置き換えることで可能です。 ・check_point(int a,int b)  テキスト座標(a,b)の文字が'*'なら1を、そうでないなら0を返す ・gotoxy(int x,int y)  テキスト座標(x,y)にカーソルを移動 ・cls()  テキストスクリーンをクリアする (テキスト座標は(0,0)~ ) UNIXのVT100端末の場合は、こちらのエスケースシーケンスで 関数を作成すれば可能かもしれません。 http://homepage3.nifty.com/peterpan/etescseq-eseq.html gotoxy(int x,int y)は、printf("\x1b[%d;%dH",y+1,x+1); cls()は、printf("\x1b[2J"); あたりで実現可能かもしれませんが、check_point(int a,int b)は 難しいかもしれません。 Windows環境ならMS-DOSモードまたはDOS窓で、IBMPC版で動かしてみると 動くと思います(PC-98xxをお使いでなければ) コンパイラはDOS用のフリーのLSI-C86でやってみてください。 http://homepage3.nifty.com/aokura/phoebe/phoebe.htm

imoyaki
質問者

お礼

WINDOWS環境ではLSIコンパイラでIBMPC版を動かせました。ありがとうございます。とりあえず実行結果がわかり助かりました。 gotoxy(),clsのエスケープシーケンスに関する考察参考になりました。

その他の回答 (3)

  • abayama
  • ベストアンサー率48% (38/79)
回答No.4

Unixの場合、画面消去や指定したカーソル位置への書き込みをエスケープシーケンスを使うのは邪道です。termcap, terminfo, cursesと言ったライブラリ(画面情報データベースからエスケープシーケンスを取得して動く)が準備されているのでこれを使ってください。

imoyaki
質問者

お礼

少し調べてみたのですがお恥ずかしながらtermcap,terminfo, cursesなどの使い方がわかりませんでした。。。私が実践するには難しそうなので、名前だけとどめさせていただきます。ご回答くださりありがとうございました。

回答No.3

#1です. やはり,私のは外してましたか...... 以下は,自己完結させるために,書きますが,たぶんご質問とは関係ないでしょう. 「ドット」と書きましたのは,たとえば,キャラクタの「%」というのを画面に出したいときに, PC98はテキストエリアというキャラクタコードを格納しておくところがあって,その内容を BIOSが画面にフォントを使って展開するわけです. この部分を,昔のマシンはBIOSとしてROMに内蔵していたので,PC98は他国語環境では 使えなかったわけです. これに対して,AT互換機など最近主流のパソコンやWindowsはテキストエリアというコードを保持しておくところが なくて,いきなりビットマップにフォント展開してしまいます.展開する部分もOSの機能として 持っています. だから,「画面にキャラクタを書いて」,「そのキャラクタコードを読む」 というときに,「画面にキャラクタを書いて」はできますが,コードが無くなっているので, 「そのキャラクタコードを読む」というのができるのかな? という気がします. ハードの構成が違うので,それを吸収するしくみが必要と言うことです. この点で,下記のような回答になってしまいました. もしも,テキストコードを画面に保持しているところがあれば,そのアドレスを 読むことは可能(容易)です. ご質問は,どうもこのテキストエリアの話のようですね. 誤解してました.すみません. 「エクステンダ」というのは,アドレスを拡張するためのしかけのはいったプログラム です.WindowsのGCCはDOSベースのソフトです.最近のはエクステンダが要りませんが, 見えないところで動いていまして,アドレスの変換をやってます. ご質問とはずれますが, ---------------------------------- 24x80の配列を容易しておいて,(普通の配列) その配列に対して読み書きをおこないつつ, 必要なら配列の内容を画面に表示させる 書き込みは  A[x][,y]=1 読み込みは  a = A[x][y] ---------------------------------- というのなら,すぐにでも作れます. プログラムの確認が主目的なんですよね? だったら,あまりインチキしてはいけませんね.

imoyaki
質問者

お礼

再度ご説明いただきありがとうございます。 教えていただいた配列を使う方法を、PC98版のエスケープシーケンスの書き換えと一緒に明日試してみたいと思います。 2次元配列を準備する。 "make_triangle()"、"make_square()"では、"gotoxy(x,y)"の"x"、"y"に対応した個所の配列の要素に"*"を入れる。 "check_point()"でその有無を検査する。 という具合で。 それにしても、Cをやっているとハードに関する知識が結構要求されるんですね。

回答No.1

私も,昔,GCCで画面にプロットするルーチンを作ったことがあります. どのようなご質問か,正確には分からないのですが,画面にドットを打ったり, そのドットが点灯しているかどうかを検出したいのでしょうか. 基本的には,PC98と(いまでは一般的なPCの)DOSVなどの環境の違いは, ビットマップ描画でして,画面=アドレス と言うことです. つまり,特定のアドレスに値をかきこむと,そのドットが点灯するのです. また,そのアドレスがいくつであるか読み出すと,ドットが点灯しているかどうかが 分かります.いたって単純です. 問題は,「特定のアドレス」です. 画面がどのアドレスに割り当てられているのかは,システムに依存しています. 私の使っていたDJGCCの場合は,確か「0xd0000000」だったかと思います. 仮想記憶という考え方があって,物理アドレスはどんなアドレスにでも マッピングできます.だから,システム(エクステンダ)がどんなマッピングをしているのか わかりませんか? アドレスさえわかれば,peek関数は簡単です. peek(adress) は *(adress) メモリ処理は,BASICよりもCの方が得意です. 特定のドットを点灯させるルーチンが作れれば,その他の関数は, それを用いて作れます.(円や,四角形,塗りつぶしなど)

imoyaki
質問者

お礼

ご回答いただきありがとうございます。ドットというよりは"*"と" "(スペース)で作るアスキーアートのようなものです。 でもこの場合 3行目:   #define VRAM 0xa000 202行目: xy=(80*b+a)*2; 203行目: dat=peek(VRAM,xy); などをみていると、"ドット"ならぬ"半角文字"を点単位とした24×80のスクリーンの各点が、特定のアドレスに割り当て割れているんでしょうかね。 浅学なもので"エクステンダ"なるものがどんなマッピングをしているのかは分かりません。。。

関連するQ&A

専門家に質問してみよう