DOSでプログラムを作ってみよう!

1.インストール

Windows全盛の時代ですが、DOSでプログラムを作ってみます。
DOSでC言語をやって作るわけですが、描画などの速度重視する部分は
アセンブラで書くのが一般的です。
しかしアセンブラを知らないとできないし、持ってない人は作りようがありません。

ここではフリーのコンパイラを使って解説していきます。
フリーはいくつか種類があるけど、TurboC++1.0を使います。
<a href="http://community.borland.com/museum/">アメリカのサイト</a>でダウンロードできますが、これにはアセンブラは含まれていません。
別のフリーのコンパイラで
DMC++というのがあるけど、こっちはインラインアセンブラが
使えるので本当はこっちの方がいいかもしれないのですが、あえてTurboC++を
使うことにします。(使い慣れているし・・)

ダウンロードしたら解凍してC:\TCPPのフォルダにコピーします。
そしてDOSプロンプトを立ち上げます。
Windowsのスタートから”ファイル名を指定して実行”を選び
command
と入力。
MS-DOSプロンプトが立ち上がったら、

C:\>CD \tcpp
C:\TCPP>

としてディレクトリを変えます。
あらかじめフォルダを出しておいてウィンドウが最前面の時にcommandを実行すれば
最初からこのディレクトリになります。

ここでコンパイルや実行を行います。
そのためのソースファイルはメモ帳で作ります。
フォルダの中に新規作成でテキスト文書を作ります。
ファイル名をtest.cppに変更します。
拡張子が出てない場合はフォルダオプションで表示するようにしてください。

メモ帳で次のように入力して保存します。

#include<stdio.h>
void main()
{
 printf("テスト\n");
}

DOSプロンプトで次のように入力

C:\TCPP>tcc test.cpp

コンパイルが成功すると、

C:\TCPP>tcc test.cpp
Turbo C++ Version 1.01 Copyright (c) 1990 Borland International
test.cpp:
Turbo Link Version 3.01 Copyright (c) 1987, 1990 Borland International

Available memory 281648

C:\TCPP>

と表示されるはずです。
ここでエラーが出ていたらよくプログラムを確認してください。

実行するにはtestと入力します。

C:\TCPP>test
テスト

2.グラフィック

準備運動はこのくらいにしてグラフィックを表示します。
グラフィックの扱いはハードごとに違います。
今回はDOS/Vだけを限定するのでハードの違いを気にする必要はありません。
詳しいことは別の本に任せるとしてとにかく表示をさせることだけを考えます。
DOSでは色んな画面のモードがあります。
主に使うのが640×480ピクセルの16色と320×200ピクセルの256色です。
ゲームでは256色が使いやすいのでライブラリもこのモード限定にします。
このモードを使うには画面モードを変更する必要があります。
その設定専用の関数SetScreenMode()を作り表示させます。

#include<stdio.h>
#include<conio.h>
#include<dos.h>
void SetScreenMode(int mode)
{
 union REGS inregs,outregs;
 inregs.x.ax=mode;
 int86(0x10,&inregs,&outregs);
}

void main()
{
 printf("画面を切り替えます\n");
 getch();
 SetScreenMode(0x13);//320*200,256色モード
 getch();
 SetScreenMode(0x3);//テキストモード
 printf("画面を戻しました\n");
}

BIOSファンクションを呼び出すためにint86命令を使っています。
アセンブラなら
asm{
mov ax,mode
int 10h
}

としているところです。
実行すると何かキーを押すと画面がフルスクリーンになるぐらいです。
なにも描いてないので本当に変わったのか分かりにくいので試しに描画を作ってみます。

このモードではメモリアドレス[A000:0000]のところからピクセルが並んでいます。
よってそこに直接書き込めばいいのです。
セグメントがA000であるのでfar型の宣言の変数にアドレスを入れて扱います。

実行すると次のようになります。

15番の色はデフォルトで白になっています。
この15番はパレット番号なのでパレットを変えれば表示も変わります。
パレットの関数を含めたものは次の通り。

#include<stdio.h>
#include<conio.h>
#include<dos.h>
#define BYTE unsigned char
void Palette(BYTE num,BYTE r,BYTE g,BYTE b)
{
 disable();
 outp(0x3c8,num);
 outp(0x3c9,r >> 2);
 outp(0x3c9,g >> 2);
 outp(0x3c9,b >> 2);
 enable();
}
void SetScreenMode(int mode)
{
 union REGS inregs,outregs;
 inregs.x.ax=mode;
 int86(0x10,&inregs,&outregs);
}
void Pset(int x,int y,char c)
{
 char far* m=(char far*)0xa0000000L;
 m[x+y*320]=c;
}
void main()
{
 printf("画面を切り替えます\n");
 getch();
 SetScreenMode(0x13);//320*200,256色モード
 for(int i=0;i<100;++i)
  Pset(i,i,15);
 getch();
 Palette(15,255,0,0);//赤
 getch();
 Palette(15,0,255,0);//緑
 getch();
 Palette(15,0,0,255);//青
 getch();
 SetScreenMode(0x3);//テキストモード
 printf("画面を戻しました\n");
}

DOSでの色表現はRGB各6ビットで26万色から選択なのですが、色の概念を
Windowsと同じにしています。
よってPaletteで指定するときは0〜255を設定してください。

main関数を次のようにすると256色同時も可能です。

void main()
{
 SetScreenMode(0x13);
 for(int a=0;a<256;++a){//パレット設定
  int r,g,b;
  r=(a&7)<<5;
  g=((a>>3)&7)<<5;
  b=((a>>6)&3)<<6;
  Palette(a,r,g,b);
 }
 int x,y;
 int t1,t2;
 for(y=0;y<200;++y){
  for(x=0;x<320;++x){
   int c=((x>>3)&15)+((y>>3)&15)*16;
   Pset(x,y,c);
  }
 }
 getch();
 SetScreenMode(0x3);
}

※LSI-C3.30試食版を使っている場合は、拡張子を.Cにして変数宣言の位置に
気をつけてください。
またdisable(),enable()命令がないので削除してください。