for - みる会図書館


検索対象: 月刊 C MAGAZINE 1992年1月号
47件見つかりました。

1. 月刊 C MAGAZINE 1992年1月号

プロ List 6 テパイスへッダアドレスの取得 List ー 31 : uns i rsv3 / * キャラクタテ・ハ・イス : 0utput until busy * / ー 32 : uns i rsv4 / * フ・ロックデハ・イス : Non Fat ID ー 34 : iOCtl / * キャラクタ / フ・ロックテ・ハ・イス ー 35 : uns i 馴 chardev : 1 : } satr ; ー 36 : / * スト万シ・・エントリ・ホ。インタのインタ unsigned int strategy; / * 割込ェントリ・ホ。インタのインタ ー 38 : uns igned i nt int_ent; union uname { 39 : unsigned char devname[ BASELEN ] : / * キャラクタ・テ・ハ・イスファイル名 40 : / * フ・ロック・テ・ハ・イス = ット数 : 41 : uns i char un i tnum ; : 42 : ー 43 : } SDEVHEAD : 44 : ー 45 : void devadr( SDEVHEAD far * ) : ー 46 : void far *getdevadr( char * ) ; ー 47 : ー 48 : int min( int argc, char *argv ロ ) ー 49 : { ー 50 : SDEVHEAD far *pdev : ー 51 : if ( argc く = 1 ) ( : 52 : fprintf( stderr, ”使用法 : devadr くデハ・イス名溿 n ” ) ; return ( 1 ) : ー 54 : ー 55 : if ( ( = getdevadr( * + + ar ) ) = NULL ) { / * テ・ハ・イス・ヘッタ・アト・レスの取得 ー 57 : fprintf( stderr, ”テ・ハ・イス Xs が見つかりません。” , *argv ) ; return( 1 ) ; は 59 : 60 : devadr( xiev ) ; return ( 0 ) ; ー 62 : 1 63 : } 64 : ー 65 : void devadr( SDEVHEAD far *Edev ) / * デハ・イス・ト・ライハ・情報の表示 printf( " DEV ヘッタ・スト万シ・割込 \ n ” ) : ー 67 : printf( ” ー 68 : printf( ” X10cXFp XNp XNp Miev—>strategy, Edev->int ent ) ; ー 69 : if ( xiev->satr. chardev ) { ー 71 : register int n; ヨ 72 : for ( n = 0 ; n く sizeof( *. devname ) ; n + + ) ー 73 : putchar( giev->u. devname[ n ] ) ; / * キャラクタ・テ・ハ・イスファイル名 * / 74 : } else printf( ”ェ外数 Xu ” , 1Hev->u. unitnum ) : putchar( ' ' ) ; ー 77 : if ( *. stdi ) printf( ” stdin ” ) : if ( *. stdo ) 1 80 : printf( ” stdout ” ) ; ー 81 : if ( *. nul ) 、 82 : printf( " nul" ) ; 83 : if ( glev->satr. clock ) ー 84 : : 85 : printf( ” clæk ” ) ; if ( Biev->satr. special ) ー 86 : printf( ” special ” ) ; putchar( '*n' ) ; ー 88 : ー 89 : } ー 90 : ー 91 : void far *getdevadr( char devnarneC] ) / * テ・ハ・イス・ヘッタ・アト・レスの取得 、 92 : { char name[ BASELEN ] : 94 : struct find_t sdta; 95 : uns igned char far *pcdev : 96 : 97 : if ( -dos-findfirst( devname, -A—NORMAL, &sdta ) ! = 0 ) ー 98 : return ( NULL ) : / * テ・ハ・イス名が見つからない ー 99 : memset( name, , BASELEN ) ; 00 : for ( n ニ 0 ; devname[ n ] n く sizeof( name ) : n + + ) d01 : : 102 : name[ n ] = ( char )toupper( devname[ n ] ) : : 103 : for ( = MK-FP( sdta. size. 1 ) ; FP-OFF( pcdev ) ! = 0 ; + + ) ( unsigned IO far *Pldev = ( 15 far * hx:dev; : 104 : : 105 : if ( pldev[ 0 ] = * ( 聞 si 10 far * ) 冊 : 1 : pldev[ 1 ] = * ( unsigned 10 far * ) ( name + 4 ) ) : 107 : / * デハ・イス名検索 break : リ 08 : q09 : return( FP-OFF( ) ? ( void far * ) ( ー 10 ) : NULL ) : q10 : 11 : } 1 : #include く stddef. h> 2 : #include く ctype. h> 3 : #include く string. h> 4 : #include く dos. h> 5 : 6 : #ifdef _TURBæ 7 : #include く dir. h> 9 : #define _dos_findfirst( p, attr, buf ) findfirst( (p), (buf), (attr) ) : 10 : #define find_t ffblk ー 11 : #define Size ff_fsize 2 : #define —A-NORMAL 0X00 3 : #endif ー 14 : : 15 : #ifndef MK_FP : 16 : #define MK-FP(), 。 ) ((void far *)(((unsigned 1 。 ) ( s ) くく 16 ) ー (unsigned)(o))) : 17 : #endif ー 18 : ー 19 : #define BASELEN / * テ・ハ・イス名の長さ ー 20 : 翊 1 : void far *getdevadr( char devnameC] ) / * テ・ハ・イス・ヘッタ・アト・レスの取得 * / 2 : { char name[ BASELEN ] : ー 23 : ー 24 : struct find_t sdta; : 25 : uns igned char far *pcdev ; : 27 : if ( _dos_findfirst( devname, _A_NORMAL, &sdta ) ! = 0 ) return ( NULL ) : / * テ・ハ・イス名が見つからない 9 : memset( name, , BASELEN ) ; 0 : for ( n : 0 ; devname[ n ] n く sizeof( name ) : n + + ) name[ n ] ニ ( char )toupper( devnameC n ] ) : 2 : for ( pcdev = MK-FP( sdta. size, 1 ) ; FP-OFF( pcdev ) ! = 0 ; pcdev + + ) ( ー 33 : 10 far *Pldev = ( long far * )pcdev; 朝 34 : 5 : if ( PldevC 0 ] ー = * ( 凹 si 馴 10 far * )name ー 36 : pldev[ 1 ] = = * ( 1 。 far * ) ( 冊 + 4 ) ) 7 : / * テ・ハ・イス名検索 : 38 : break; : 39 : return( FP-OFF( pcdev ) ? ( void far * ) ( pcdev ー 10 ) : NULL ) : ー 40 : 1 : ) 8 テパイスドライバ情報表示ユーティリティ List 1 : #include く stdiO. h> 2 : #include く ctype. h> 3 : #include く string. h> 4 : #include く dos. h> 5 : 6 : #ifdef _TURBOC 7 : #include く dir. h> 8 : 9 : #define _dos_findfirst( p, attr, buf ) findfirst( (p), (buf), (attr) ) 10 : #define find_t ffblk 11 : #define size ff_fsize 12 : #define _A_NORMAL 0X00 13 : #endif 14 : 15 : #ifndef MK_FP 16 : #define MK-FP(s,o) ((void far * ) ( ( ( 聞 si 1 。 ) ( s ) くく 16 ) (unsigned)(o))) 17 : #endif 18 : 19 : #define BASELEN / * テ・ハ・イス名の長さ 事 / 20 : 21 : typedef s truct devs truc ( / * テ・ハ・イス・ヘッタ・ / * 次のテ・ハ・イス・ヘッタ・を指すインタ * / struct devstruc far *pnextdev; 22 : struct { / * 属性 23 : / * 標準入力装置 uns igned stdi 24 : / * 標準出力装置 uns i stdo 25 : / * NUL デハ・イス uns i nul 26 : / * 如ックデハ・イス clock uns i 27 : / * 特殊装置 uns igned 28 : uns i 馴 29 : / * Oßm/CIose/RemovabIe uns rsv2 ー 30 : 8 ネ / 1 人 1 よ 1 、 1 1 人 1 よ 90 C MAGAZINE 1992 1

2. 月刊 C MAGAZINE 1992年1月号

NUL デバイスのテパイスへッダアドレスの取得 List テパイス名変更 ユーティリティ それて、はお遊びの簡単なユーティリティ を紹介します。 MS-DOS て、は REN コマンド , RENDIR コ マンドてファイル名やディレクトリ名を変 更することがて、きますが , デバイス名は変 更することがて、きません。通常はデバイス 名を変更することはないため , 問題ありま せんが , ファイル名やディレクトリ名より もデバイス名のほうが優先されるため , デ バイス名を変更したくなることもあります。 たとえば , PC ー 9801 シリーズや FM-TOW NS て、はクロックデバイスは 'CLOCK ' て、 すが , そのため , CLOCK. ASM というファ イルをオープンすることがて、きません。ク ロックデバイスというのはユーザが使用す ることはまずありませんが , ほかのマシン ( たとえば IBM ー PC 互換機 ) て、は ' CLOCK ' 以外のデバイス名になっています。した がって , ほかのマシンて、作成された CLOCK. ASM というファイルをコヒ。ーする際に問題 となります。 テパイス名変更 ユーティリティの使用法 使用法 : rendev oldname newname 使用法は簡単て , oldname を newname に 変更します。デバイス名は 8 バイトのため , 9 バイト以上指定しても無視します ( 工ラー とはせずに 9 バイト目以降を切り捨てます ) 。 また , 指定されたデバイス名は大文字に変 換しています。このとき漢字コードを考慮 していないため , 漢字のデバイス名には対 応していません ( 筆者は漢字のデバイス名に お目にかかったことがないため , 対応しま せんて、した ) 。 ソースリストを List 3 に示します。 NUL デバイスのデバイスへッダアドレスの取得 には List 1 を用いています。 非常に簡単なプログラムて、すから , 詳細 1 : #include く stddef. h> 2 : #include く dos. h> 3 : 4 : #ifndef MK FP 5 : #define MK FP(s,o) ((void far * ) ( ( ( 聞 si 馴 1 。 ) ( s ) くく 16 ) ー (unsigned)(o))) 6 : #endif 7 : 8 : void far *getdosvar( void ) : 9 : 10 : void far *getnuldev( void ) / * NUL テ・ハ・イスのテ・ハ・イス・ヘッタ・アト・レスの取得 * / unsigned char far *pcdev; 12 : 13 : for ( = getdosvar() : FP-OFF( ) ! ニ 0 : de い + ) { 14 : unsigned 10 far *pldev = ( 10 far ネ )IF-•dev; 15 : 16 : if ( pldev[ 0 ] = 0X204C554eL pldev[ 1 ] = 0X20202020L ) 17 : 検索 * / / ネテ・ハ・イス名 ' NUL break; 18 : 19 : return( FP-OFF( pcdev ) ? ( void far 事 ) ( pcdev ー 10 ) : NULL ) : 21 : ) 22 : 23 : / * 返り値内部変数領城のアト・レス 24 : 25 : * / 26 : void far *getdosvar( void ) 27 : ( struct SREGS segs ; 28 : union REGS iregs; 29 : 30 : iregs. h. 曲 : 0X52 : 31 : intdosx( &iregs, &iregs, &segs ) ; 32 : return( MK—FP( segs. es, i regs. x. bx ) ) : 33 : 34 : } / ネ内部変数領城のアト・レスの取得り NUL テパイスのテパイスへッダアドレスの取得 LiSt 1 : #include く stddef. h> 2 : #include く dos. h> 3 : 4 : # i fdef 5 : #include く dir. h 〉 6 : 7 : #define _dos_findfirst( p, attr, buf ) findfirst( (p), (buf), (attr) ) 8 : #define find_t ffbl k 9 : #define size ff_fsize 10 : #define A_NORMAL 0X00 11 : #endif 12 : 13 : #ifndef MK_FP 14 : #define MK-FP(s,o) ((void far の ( ( ( 凹 si 1 。 ) ( s ) くく 16 ) ー 15 : #endif 16 : 17 : void far *getnuldev( void ) / * NUL デハ・イスのテ・ハ・イス・ヘッタ・アト・レスの取得 * / 18 : ( struct f ind_t sdta ; char far *Dcdev: 20 : 21 : 22 : 23 : 25 : 28 : 29 : 30 : if ( —dos-findfirst( "NUL ” , -A-NORMAL. &sdta ) ! = 0 ) / * NUL テ・ハ・イスが見つからない return( NULL ) ; for ( = MK-FP( sdta. size, 1 ) : FP-OFF( pcdev ) ! = 0 ; + + ) ( unsigned far *Pldev = ( 10 far * if ( pldevC 0 ] = 0X204C554eL pldev[ 1 ] = = 0X20202020L ) 検索り / * テ・ハ・イス名 ' NUL break; return( FP-OFF( ) ? ( void far * ) ( ー 10 ) : NULL ) : 86 C MAGAZINE 1992 1

3. 月刊 C MAGAZINE 1992年1月号

新 MS ー DOS プロクラミング入門 C ログラマのための LISt テパイス名変更ユーティリティ はソースリストを参照してください。動作 確認は PC ー 9801 シリーズ MS-DOS Ver. 3. 3B と FM-TOWNS MS-DOS Ver. 3.1 て、 行っています。 テパイスドライバチェーン 表示ユーティリティ もうひとつ簡単なユーティリティを紹介 します。自作のデバイスドライバをデバッ グするときにはデバイスドライバが登録さ れた領域を知りたくなることがあります。 デバイスドライバが登録された領域がわか ればデバイスドライパ内の内部変数を確認 することて、 , 内部からデバッグが可能とな ります。 それて、はデバイスドライバのチェーンを 表示するユーティリティを List 4 に示しま す。 NUL デバイスのデバイスへッダアドレ スの取得に List 2 を使用しており , NU13 バイスから順に Table 2 のデバイスへッダの [ 十 0 ~ 十 3 ] の次のデバイスへのポインタ をたどりながら , デバイスへッダの情報を 表示しています。 詳細はソースリストを参照してください なお , 動作確認は PC ー 9801 シリーズ MS-DO S Ver. 3.3B と FM-TOWNS MS-DOS Ve r. 3.1 て、行っています。 任意のテパイスへッダ アドレスの取得 デバイスドライバのチェーンをいちいち 先頭からたどるのはめんどうなため , DOS ファンクション 4Eh て、直接取得する関数を L ist 5 に示します。この関数を使用して , 指 定されたデバイス名のデバイスドライバ情 報だけを表示するユーティリティを List 6 に 示します。 詳細はソースリストを参照してください 動作確認は PC ー 9801 シリーズ MS-DOS Ver. 3.3B と FM-TOWNS MS-DOS Ver. 3.1 て、行っています。 1 : #include く stdio. h> 2 : #include く ctype. h> 3 : #include く string. h> 4 : #include く stdl ib. h> 5 : #include く dos. h> 6 : 7 : #ifndef MK_FP 8 : #define MK_FP(s,o) ((void far 1 。 ) ( s ) くく 16 ) ー (unsigned) ( 0 ) ) ) 9 : #endif 10 : 11 : #def ine ERR / * ェラー時のリターン・コート・ 12 : #define NOERR 13 : #define BASELEN / * ファイル名のヘ・一ス部分の長さ ネ / 14 : 15 : typedef struct devstruc ( / * テ・ハ・イス・ヘッタ・ / * 次のテ・ハ・イス・ヘッタ・を指す本。インタり 16 : struct devstruc far *pnextdev; struct { / ネ属性 17 : / * 標準入力装置 uns stdi / * 標準出力装置 19 : uns i 馴 stdo / * NUL テ・ハ・イス nu 1 20 : / * 如ックテ・ハ・イス clock 21 : uns / * 特殊装置 22 : uns 23 : / * 0Em/Close/RemovabIe り 24 : unsignai rsv2 rsv3 25 : / * キャラクタテ・ハ・イス : 0utput until busy * / uns 26 : rsv4 / * フ・ロックテ・ハ・イス : Non Fat ID 28 : ioctl / * キャラクタ / フ・ロックテ・ハ・イス uns i chardev : 1 : } satr; 30 : uns igned i nt / * スト万シ・・エントリ・本。インタのインタ 31 : s trategy , / * 割込工ントリ・本。インタのホ。インタ 32 : uns i nt int_ent; union uname { 33 : uns i char devname [ BASELEN ] : / * キャラクタ・デハ・イスファイル名 34 : / * フ・ロック・デハ・イス = ット数 35 : uns char un itnum; 36 : 37 : } SDEVHEAD : 38 : 39 : int rendev( char * , char * ) ; 40 : void far *getnuldev( void ) , far *getdosvar( void ) : 41 : void usage( void ) : 42 : 43 : int min( int argc, char *argv[] ) 44 : { r.h ” nldnamr BASELEN 工 newnam[ BASELEN 」 . *pnam int n; 47 : if ( argc ← 2 ) 48 : usage() ; / * 使用法表示 50 : ænset ( 0 ldnam, , BASELEN ) : 51 : memset ( newnam, , BASELEN ) : for ( n = 0 , : * + + ar ; *pnam n く BASELEN; n + + , p m + + ) 52 : oldnamC n ] = ( char *pnam ) : 53 : for ( n = 0 , ニ事 + + ar ; 夘 n れく BASELEN; n + + , p m + + ) 54 : newnamC n ] = ( char )toupper( *pnam ) : if ( rendev( oldn 明 , newnam ) = NOERR ) / * テ・ハ・イス名変更 return ( 0 ) : fputs( " テ・ハ・イス名が見つかりません。 #n", stderr ) : 58 : return( 1 ) : 60 : } 61 : 62 : int rendev( char oldn 明 [ ] , char newnamC] ) 63 : { 64 : SDEVHEAD far *vHevhead : 65 : if ( ( pievhead : getnuldev() ) = NULL ) 66 : / * NUL テ・ハ・イスが見つからない return ( ERR ) : for ( : FP_OFF( ) ト 0xffff; pdevhead = ) { 68 : / 本テ・ハ・イス・ト・ライハ・のチェーンをたどるり 69 : if ( pdevhead->satr. chardev ) { / * キャラクタ・テ・ハ・イス ? if ( ( ( long far 事 )pdevhead->u. devname ) [ 0 ] = ( ( long 事 ) 01 面 am ) [ 0 ] ( ( long far 事 )pdevhead->u. devname ) [ 1 ] 73 : = ( ( long * )oldnam ) [ 1 ] ) ( 74 : ネ ( union uname 本 )newnam; gievhead->u = 75 : return( NOERR ) : / 事デハ・イス名変更 76 : 77 : 0 本 / / ネテ・ハ・イス名変更 0 新 MS-DOS プログラミング入門 87

4. 月刊 C MAGAZINE 1992年1月号

ロラマのめの Li st 4 アレンスマニュアル』 V01. 1 , V01. 2 , N EC [ 13 ] 「 MS-DOS 3.3B ューザーズリファレ ンスマニュアル』 , NEC [ 14 ] TMS-DOS 工ンサイクロペディア V olume 1 システム解説編』 , アスキー [ 15 ] fMS-DOS 工ンサイクロペディア V olume 2 リファレンス編』 , アスキー [ 16 ] fMicrosoft C 6.00A Professional D evel opment System Programming Guide 』 , Microsoft [ 17 ] fMicrosoft C 6.00A ProfessionaI D evel opment System ReferenceJ , M icrosoft [ 18 ] fMicrosoft C 5.1 Optimizing Com piler User' s Guide 』 , Microsoft [ 19 ] fMicrosoft C 5.1 Optimizing Com piler Language Reference , Micr osoft [ 20 ] fMicrosoft C 5.1 Optimizing Com piler Mixed Language Programmi ng GuideJ , Microsoft [ 21 ] fMicrosoft C 5.1 Optimizing Com pi ler Run- Time Library Reference 1 , 2 』 , Microsoft [ 22 ] TTURBO C 2.0 USER' S GUID E 』 , BORLAND [ 23 ] fTURBO C 2.0 REFERENCE GU IDE 』 , BORLAND [ 24 ] 「 TURBO C 十十 1.0 INTRODUCT IONJ , BORLAND [ 25 ] 「 TURBO C 十十 1.0 USER' S GUI DE 』 , BORLAND [ 26 ] TTURBO C 十十 1.0 PROGRAMM ER' S GUIDE 』 , BORLAND [ 27 ] TTURBO C 十十 1.0 LIBRARY R EFERENCEJVol. 1 , V01. 2 , BORL AND [ 28 ] 「 LSI C ー 86 Ver 3.2 試食版ューザー スマニュアル』 , 工ル・エス・アイジ ヤノヾン 24 : 25 : 26 : 28 : 29 : 30 : 32 : 33 : 34 : 35 : 36 : 37 : 38 : 39 : } SDEVHEAD; 40 : 41 : void devdisp( SDEVHEAD far * ) : 42 : void far *getnuldev( void ) : 43 : 44 : int min( void ) 45 : ( 46 : SDEVHEAD far *Pdev; if ( ( = getnuldev() ) = NULL ) ( 48 : fprintf( stderr, ” NUL テ・ハ・イスが見つかりません。新” ) : return ( 1 ) : 50 : devdisp( pdev ) ; 52 : return( 0 ) : 53 : 54 : ) 55 : 56 : void devdisp( SDEVHEAD far *pdevhead ) / * デハ・イス・ト・ライハ・チェーン表示 57 : { printf( ” DEV ヘッタ・スト万シ・割込 \ n ” ) ; 58 : printf( ” 59 : do { / * デハ・イス・ト・ライハ・のチェーンをたどる 60 : pr intf ( ” % 10cXFp XNp XNp 62 : if ( pdevhead->satr. chardev ) ( 63 : 64 : register int Ⅱ ; 65 : for ( n = 0 : n く sizeof( pdevhead->u. devname ) ; n + + ) 66 : putchar( 〉 u. devname[ れ ] ) : / * キャラクタ・テ・ハ・イスファイル名 68 : ) else 69 : printf( " = ット数 Xu ” , pdevhead->u. unitnum ) ; putchar( ' 71 : if ( pdevhead->satr. stdi ) printf( " stdin ” ) : if ( pdevhead->satr. std0 ) 74 : printf( ” stdout" ) : if ( pdevhead->satr. nul ) printf( ” nul ” ) : 77 : 第 if ( pdevhead->satr. clock ) printf( " clock" ) : if ( pdevhead->satr. ) 80 : printf( " sEmiaI" ) : putchar ( ' *n' ) : 82 : xievhead : gievrmd->pnextdev;/* 次のテ・ハ・イス・ヘッタ・を指す本。インタり 83 : } while ( FP—OFF( xievhead ) ! = 0xffff ) ; 84 : 86 : 87 : void far *getnuldev( void ) / * NUL デハ・イスのテ・ハ・イス・ヘッタ・アト・レスの取得 * / ツ 89 : struct find_t sdta; 90 : uns igned char far *pcdev : 91 : if ( _dos_findfirst( ” NUL", —A-NORMAL, &sdta ) ! = 0 ) 92 : / * NUL テ・ハ・イスが見つからない return ( NULL ) ; for ( pcdev = 盤 FP( sdta. size, 1 ) ; FP-OFF( EEdev ) ト 0 : de い + ) ( 94 : unsigned 10 far *pldev = ( 10 far * 95 : 96 : 第 if ( PldevC 0 ] = 0X204C554eL pldev[ 1 ] = 0X20202020L ) / * テ・ハ・イス名 'NUL 検索り 98 : break : 99 : return( FP-OPF( x:dev ) ? ( void far * ) ( pcdev - 10 ) : NULL ) : 100 : 101 : ) / * 特殊装置 / * キャラクタテ・ハ・イス : 0utput until busy * / / 事フ・ロックテ・ハ・イス : Non Fat ID / * キャラクタ / フ・ロックテ・ハ・イス / * スト方シ・・エントリ・ホ。インタのインタ * / / * 割込工ントリ・ホ。インタのホ。インタ / * キャラクタ・テ・ハ・イスファイル名 / * フ・ロック・テ・ハ・イス = ット数 、 1 6 1 よ 1 人 1 よ srmial ・ uns i 馴 rsvl uns rsv2 uns rsv3 uns i 馴 rsv4 iOCtl unsignai chardev : 1 ; ) satr : uns i nt strategy; int_ent; union uname ( char devname[ 8 ] : char unitnum; 新 MS-DOS プログラミング入門 89

5. 月刊 C MAGAZINE 1992年1月号

Fig ・ 4 実行ファイルの作成方法 ( 改良版 ) Fig ・ 3 List 3 の実行結果 A> わ list4, 1i3t4 : AW.J /c /AL list2. c A>LINK /næ 1 ist4 + 1 ist4. list4; A> A> A> A > い 3 A>a A>b A> 5510 5512 -2 13205 13205 -29754 INS REP VOID NWL SI SU CU CI INS REP VOID NWL SU SI CA 配列のアドレス List こう考えると , C の関数はミディアムモデ ルて、なくラージモデルにしたほうがよさそ うて、す。 もちろんミディアムモデルて、 , 引数とし て受け取るポインタを far;tk インタとするこ ともて、きます。しかし , この場合は将来の 拡張などを考えても大したメリットはあり ません。 List 2 の C プログラムはそのままて、よいの て、すが , List 1 の BASIC プログラムは , Li st 4 のように記述する必要があります。 メモリモデルの変更にともない , コンパ イル・リンクは Fig. 4 のように行う必要があ ります。 これて、正しく動作するようになりました。 SEG far ポインタを使うためには SEG キー ワードが必要です。この呼び出しでは , 対応する引数のセグメントおよびオフ セットが渡されるようになります。 前回は , malloc による配列の動的な確保 について解説しましたが , QuickBASIC と c をリンクさせるときは , 注意が必要て、す。 コラム℃て、のメモリ確保』を参考にしてく ださい 0 0 00 00 ・ 1 つな 4 戸 0 6 叮ー 8 9 いに ( 」にい」りい一いいに List 1 の修正プログラム List BYVAL nX, 1 : DECLARE SUB rank CDECL (SEG a as INTEGER, SEG r as INTEGER, 2 : DIM n AS INTEGER, k AS INTEGER, i AS INTEGER BYVAL MaxX, SEG count as INTEGER) 4 : INPUT ”生徒数” ; n 5 : INPUT ”テストの回数” ; k 6 : 7 : DIM a(0 TO n-l) AS INTEGER, r(0 TO n-l) AS INTEGER 8 : DIM Max AS INTEGER 9 : DIM adderA AS INTEGER, adderR AS INTEGER, adderC AS INTEGER : 10 : ー 11 : Max = 100 * k : 12 : DIM count(0 TO Max + 2 ) AS INTEGER : 13 : ー 14 : FOR i = 0 TO n- 1 PRINT ” data ” ; i + 1 ; INPUT a(i) 16 : : 17 : NEXT ・ 19 : CALL rank()( の , r( の , n, Max, count( の ) ー : 20 : ー 21 : FOR i = 0 TO n ー 1 PRINT ” data ” : i + 1 ; ー 22 : : 23 : NEXT ma 日 OC 使用上の注意 Jum= 0 148 C MAGAZINE 1992 1

6. 月刊 C MAGAZINE 1992年1月号

List 3 80 : 82 : 83 : void far *getnuldev( void ) / * NUL デハ・イスのデハ・イス・ヘッタ・アト・レスの取得 84 : { unsigned char far *pcdev; 85 : 86 : for ( pcdev ニ getdosvar() ; FP-OFF( pcdev ) ! = 0 ; + + ) ( unsigned long far *Pldev = ( unsigned 10 far * )pcdev; 88 : 89 : : 0X204C554eL p ldev[ 1 ] = 0X20202020 し ) if ( pldev[ 0 ] : 90 : / ネ 'NUL チェック break; 92 : return( FP_OFF( pcdev ) ? ( void far ネ ) ( pcdev ー 10 ) : NULL ) : 93 : 94 : } 95 : 96 : / * 97 : 返り値内部変数領域のアト・レス 98 : り 99 : void far *getdosvar( void ) 100 : { struct SREGS segs; 101 : union REGS iregs; 102 : 103 : iregs. h. 曲 = 0X52 : 104 : intdosx( &iregs. &iregs, e ) : 105 : return( hK_FP( segs. es, iregs. x. bx ) ) ; 106 : 107 : 108 : 109 : void usage( void ) / * 使用法表示 110 : { static char 本 g ロ : { 111 : ” \ 033 [ 36 市・ハ・イス名変更ューティリティ ハ・一シ・ヨン 0.01 \ n ” 112 : ” Copyr ight (C) 1991 N. Nakash i \ 033 ” 113 : ”使用法 : rendev oldname newname%n#n ” 114 : 115 : 116 : 117 : register char **pmsg = msg; 118 : while ( **pmsg ) 119 : fputs( *pmsg + + , stdout ) : 120 : exit( 1 ) ; 121 : 122. おわりに 今回はデバイスドライバを内側から簡単 に眺めてみました。自作のデバイスドライ バをデバッグするときなどに役立つはずて、 す。また , デバイスドライバのチェーンに 割り込むことにより , コマンドラインから デバイスドライバを登録することも可能て、 す。少々難しくなりますが , その気になれ ば ADDDRV/DELDRV コマンドを自作する こともて、きます。次回はキャラクタデバイ スを登録する ADDDRV/DELDRV コマンド を解説します。 [ 参考文献 ] [ 1 ] 中島信行 , 「 MS-DOS メモリ管理ソフ ト技法」 , 『別冊インターフェース』 , CQ 出版社 [ 2 ] 中島信行 , 「 C 言語によるメモリ管理技 法」 , 『別冊インターフェース』 , CQ 出 版社 [ 3 ] 中島信行 , 「 TSR 型デバイスドライバ の作成」 , 『インターフェース』 1990 年 2 月号 [ 4 ] 幸田敏記 , 「マシン語クックプック M S-DOS 』 , BNN [ 5 ] 幸田敏記 , 『 MS-DOSi•—タブッ ク』 , ラジオ技術社 [ 6 ] 「 J ー 3100 シリーズテクニカルマニュア ル ( ソフトウェア編 ) V3.1 』 , 東芝 [ 7 ] 『 J ー 3100 シリーズテクニカルマニュア ル ( ソフトウェア編 ) V2.11 』 , 東芝 [ 8 ] 「エッ ! MUS-DOS うらわざ手帳 ? 」 , 『年刊 AhSKI! 』 1987 年 4 月 , アスキー [ 9 ] TMS-DOS 3.1 プログラマーズリファ レンスマニュアル』 , NEC CIO]TMS-DOS 3.1 マクロアセンプラマニ ュアル』 , NEC CII]TMS-DOS 3 、 1 ューザーズリファレン スマニュアル』 , NEC [12] 『 MS-DOS 3.3B プログラマーズリフ return( ERR ) ; / * 内部変数領域のアト・レスの取得 ーン表示ユーティリティ テパイスドライバチェ 凵 St 1 : #include く stdiO. h> 2 : #include く dos. h> 3 : 4 : #ifdef 5 : #include く dir. h> 6 : 7 : #define -dos_findfirst( p, attr, buf ) findfirst( (p), (buf), (attr) ) 8 : #define find t ffblk 9 : #define Size ff fsize 10 : #define _A_NORMAL 0X00 11 : #endif 12 : 13 : #ifndef MK_FP 14 : #define MK-FP(s,o) ((void far *)(((unsigned 10 咫 ) ( s ) くく 16 ) ー (unsigned)(o))) 15 : #endif 16 : 17 : tYEHief s truct devs truc { / ネデハ・イス・ヘッタ・ 18 : / ネ次のテ・ハ・イス・ヘッタ・を指すホ。インタり struct devstruc far *pnextdev; struct { 属性 ネ / 19 : / * 標準入力装置 20 : ネ / stdi ″標準出力装置 21 : uns i 馴 stdo uns i / * NUL デハ・イス 22 : nu 1 uns i / * クロックデハ・イス clock 1 よ 1 ・・ 1 人 1 ー 4 23 : 1 2 1 88 C MAGAZINE

7. 月刊 C MAGAZINE 1992年1月号

C MAGA セミナ司トム プログラミング添削 アドバイザー / 柴田望洋 第 17 回 C と BAS 旧のリンク ( 2 ) 中学校の教師をされているマンティスさんは QuickBAS ー C と QuickC のリンクに挑戦していますか , 思ったようにいかないよう です。前回は C 言語の配列の動的確保の方法について解説しました。 今回は C と BAS ー C のリンクについて解説しましよう。 マンティスさんのプログラムの問題は , なければなりません。 以下の 2 点て、した。 今回は , 実際にバグの原因を探索し , 解 ① C 関数のコンパイル時に , 配列の宣言部で 決していくというストーリーにのっとって 工ラーが発生する 解説していきます。 ②コンバイルエラーが出ないバージョン (Q ■マンティスさんのプログラム uickBAS ℃と QuickC をリンクしたもの ) で , 期待した実行結果が得られない 前回は①を解決するために C 言語て、の配列 マンティスさんのプログラムを List 1 (B の動的確保について解説しました。残る② ASIC 部 ) および List 2 ( C 部 ) に示します。 B の問題点て、ある BASIC と C のリンクを解決し ASIC プログラム先頭の DECLARE 文は , C 言語のプロトタイプのようなものて、す。値 マンティスさんのプログラム ( BAS ℃部 ) を返す関数て、あれば DECLARE FUNCTION と , 値を返さない関数てあれば DECLARE SUB と宣言します。 CDECL は C のリンケージを指定するもの て、す。一般に C の関数名などの識別子には が付加されることが多いようて、す。すなわ ち rank という関数は , オプジェクトファイ ル中ては rank という名前に変ってしまいま す。 CDECL の指定により , C とのリンクを 確実なものとします。 さてコンパイルおよびリンクの作業は , Fig. 1 のように行っているとのことて、す。 Q uickBASIC て、は , 関数の呼び出しを far コー ルて、行うため , C 関数側は , ミディアム / ラ ■添削のポイント 今月のプログラムプロフィール 質問者 : マンティス ( 徳山市 ) 学力テストなどの順位 ( rank ) づけに利 用するアルゴリズムを QuickBAS ℃と Q uickC で記述しています。 LlSt ー、ヨは 1 : DECLARE SUB rank CDECL (BYVAL aX, BYVAL rX, BYVAL nX, BYVAL MaxX, BYVAL countX) 2 : DIM n AS INTEGER, k AS INTEGER, i AS INTEGER 4 : INPUT ”生徒数” ; n 5 : INPUT ”テストの回数” ; k 6 : 7 : DIM a(0 TO n-l) AS INTEGER, r(0 TO n-l) AS INTEGER 8 : DIM Max AS INTEGER 9 : DIM adderA AS INTEGER, adderR AS INTEGER, adderC AS INTEGER ー 10 : : 11 : Max = 100 * k ー 12 : DIM count(0 TO Max + 2 ) AS INTEGER : 14 : FOR i = 0 TO n-l PRINT ” data ” ; i + 1 : ー 15 : INPUT a(i) ー 17 : NEXT 19 : adderA = VARPTR()( の ) : adderR = VARPTR()( の ) : adderC = VARPTR(count( の ) 、 20 : rank adderA, adderR, n, Max, adderC ョ 21 : : 22 : FOR i = 0 TO n ー 1 PRINT ” data ” ; i + 1 : ョ 23 : ・ 24 : NEXT JUm= 146 C MAGAZINE 1992 1

8. 月刊 C MAGAZINE 1992年1月号

Q Lattice C V86/RT で , 割り込 み制御のタスクとして「仮想 86 モー ド」のタスクを使用できますか ? A 残念ながら仮想 86 モードのタ スクは使用て、きません。割り込み 処理タスクとしては , リアルモー ドのタスクを使用してください 仮想 86 モードはプロテクトモー ドの状態て、 8086 リアルモードの環 境をエミュレーションしています。 プロテクトモード実行中の割り込 み処理は , IDT (lnterrupt Descri pter Table) に登録する必要があり ます。 Lattice C V86/RT は , 割り込み 処理タスクの仮想 86 モードての実 行をサポートしていませんのて , 割り込み処理タスクの指定は , リ アルモードタスクに指定してくだ Q interrupt キーワードの使い方 を教えてください。また , べクト ルの設定はどのようにやるのかも 教えてください。 A 関数名の前に interrupt キーワ ードをつけて interrupt 宣言を行う とその関数は , 全レジスタが , 自 動的に待避 , 復帰され , ルーチン の終了は ret 命令の代わりに , iret 命 令に展開されます ( 付録ディスク収 録 LISTI 参照 ) 。 MS-DOS 環境て は , べクトルの設定には , DOS フ アンクション 25H を使用してくださ ROM 化するなど , MS-DOS の環 境てはない場合には , far;* インタ を用いて , べクトルテープルに直 ライフボート lnformation from CompiIer Makers 10 : り 14 : ( 25 : ) 37 : り 52 : ) 接書き込んて、ください List 2 は , interrupt キーワードを 使って , 割り込み処理を行う関数 を定義して , それをベクトルに設 定する常駐プログラムの例て、す。 List 2 のプログラムは付録ディスク に収録した LIST3 のプログラムて 呼び出します。 List 2 を例に , La tticeC による割り込み記述および 常駐プログラムの注意点を以下に あげます。 ①常駐プログラムのメモリを開放 するのに必要なプログラムセグ メントプレフィックス (PSP) の アドレスは , far ポインタの外部 変数 PSP に設定されています。 ② List 2 て、は , 割り込み関数の中て、 putch 関数を使っていますが , 般には , 割り込み関数の中ては , DOS ファンクションを呼び出す 関数は , 使用てきません。これ は , MS-DOS のファンクション が再入可能 ( リエントラント , あ るルーチンが実行中に割り込み などによって , その実行が一時 止められ , 同じルーチンが別の 所からもう一度 , 呼ばれても , 正しく実行て、きるようなルーチ ンのこと ) てあるように作られて いないからて、す。 List 2 の場合 は , 割り込みが呼ばれるのは , 明らかにユーザアプリケーショ ンからてあり , DOS ファンクシ ョンに再入することがないのて , 使用しています。 ③常駐終了する場合には , 環境変 数が格納されている , 環境プロ ックを開放しておく必要があり ますが , 環境プロックがあるセ グメントは , PSP の 0x2C バイト 目にあるのて , 外部変数 PSP を 使って , これを取得し , DOS フ アンクション 49H を使って , 開放 しておきます。 ④常駐終了の DOS ファンクション 0X31 には , 常駐するプログラム が専有するメモリの大きさを渡 す必要があります。 LatticeC て、 は , プログラムの大きさは , un signed short 型の外部変数 TSIZ E ( パラグラフ ( 1 ヾイト ) 単位 ) に 格納されています。ただし , List 2 5 : extern si short —TSIZE; 4 : extern 曲” far 事 _PSP; 2 : #include く dos. h> 1 : #include く s io 〉 48 : 45 : 44 : 32 : 26 : 24 : 23 : 21 : 20 : 19 : 17 : 15 : 8 : 3 : Lattice C H に渡すメモリの大きさも変更 わせて , DOS ファンクション 31 それらを残すならば , それに合 ヒープ領域を確保し , 常駐時に みません。 malloc 関数などて、 , せた大きさて , ヒープ領域を含 大きさ ( スタックを含む ) を合わ さと静的なデータセグメントの れは , コードセグメントの大き しなければなりません。 7 : M S ー D 0 S のファンクションが使えない場合には、設定するべクトル ( この場合 i れ t 6 0 H ) のペクトル・テーブル・アドレスを設定しておきます . 9 : unsigned short far far V ー T ロ = (unsigned short far 事 far の ( 0 0 事 4 ) : 11 : void interr 叩 t b.lz(es,ds,di,si, bp,sp, bx. dx,cx, , ip,cs, fl ) 12 : short es,ds,di,si,bp,sp,bx,dx.cx.ax.ip.cs.flag, 13 : / 事仮引数を言することにより、レジスタの値を参照できます . り int i; if()x = 255 ) ( 18 : / * が 2 5 5 ならば、割り込みハンドラを開放するために、 ー P のセグメント・アドレスを返す return; 22 : / * 回だけ、ベルを鳴らすり for(i = 0 : i く : i + + ) putch(' \ X07 ' ) : 27 : main() 29 : union r; 30 : struct 駅 S s; 31 : char far *Ptr; 34 : MS ー DOS のファンクションが使用できない場合には、直接、ペクトル・テープルに 35 : 書き込んで設定します。 36 : *VEC_TABLE = (unsigned short far の加 z : 38 : ptr = (char far *)buz; 39 : s. ds = FP_SEG(ptr); 40 : r. x. dx : FP_0PF(ptr); 41 : 「 . h. al = 0X60 : / 事割込み番号 6 0 を使用 * / 42 : r. h. 曲 = 0X25 : D 0 S ファンクション 2 5 H ペクトル設定り 43 : intdosx ( & 「 , &r, (s) : = * ( si short *)(-PSP + 0x2c); S. es 46 : 「 . h. 曲 = 0X49 ; / * D 0 S ファンクション 4 9 H メモリプロックの開放り 47 : intdosx(&r, & ら (s); ″環境プロックの開放り 「 . X. dX TSI ZE : 49 : 「 . h. al = 0 : / 本リターン・コードり 50 : r. h. ah : 0X31 : / 事 D 0 S ファンクション 3 1 H 常駐終了り 51 : intdos(&r, &r); lnformation from (hmpiler Makers 161

9. 月刊 C MAGAZINE 1992年1月号

List 1 をプロットしたければ , 単純に ( 20 , 10 ) の 位置の画素を。 n にする〔光らせる〕だけて、 す。しかし , 仮想の 500X500 のモードて、は , 座標値を 2 て、割って , ( 10 , 5 ) としなければ なりません。それから , たとえばそこに 3 番 のデイザーパターンをマップするのなら , ( 10 , 5 ) をその上左隅として使います。そし て実際の物理的な画素としては , ( 20 , 10 ) , ( 21 , 10 ) , ( 21 , 11 ) の三つを on にし , ( 21 , 10 ) を off にします〔 Fig. 1 の Shade 3 を実 現〕。 こういうデイザーパターンは , チェッカ ーゲームの盤のようだ , とお思いになった て、しよう。しかし非常に高精細のモニタを 使えば , チェッカー盤のようなギザギザは 目立たなくなります。画面上の面積がそん なに大きくなければ , あまり気になりませ ん。 モニタが十分に高精細て、あれば , 仮想画 素を構成する実際の画素がたいへん小さい のて、 , 隣接する二つの画素の色が違ってい ても , 肉眼て、はその二つを区別て、きません。 また , 視覚的補間 (visual interpolation) と いう脳の機能のために , 人間の目はパター ンの欠けた部分を適当に補って見ようとし ます。 目にはギザギザが見えていても , 脳はこ れらのデイザーパターンを , なだらかな陰 影を形成している大きな画素としてのみ , 見ようとします。私を信じない方は , カラ ーモニタやテレビの画面 , あるいは本誌の 写真を , 近くから見てみてください 2 x 2 のモノクロのデイザーパターンを使 って , 5 段階のグラデーションを作るのは実 に簡単て、したが , しかし一般的には , ディ ザリングはそんなに容易て、はありません。 色数が増えたり , デイザーパターンのサイ ズが大きくなると , 使うべきパターンも簡 単には分かりません。 たとえば , 256 色のカラーパレットに対し 0 、↓ , ↓介 0 0 00 0 1 0 1 ムり 0 、 1 0 00 1 よ 1 △りな 0 0 0 介 0 00 りり 0 っ 0 れ 0 、↓りなり 0 0 0 0 り 0 っ 0 りり 29 : 30 : 31 : 32 : 33 : 34 : 35 : 36 : 38 : 39 : 40 : 41 : 42 : / * デイザーマスク用のメモリスペース * / 43 : 44 : char dither 咫 sks [ 489 ] [ 4 ] ; 45 : 46 : / * F U N C T 1 0 N S : 関数 * / 47 : Create_Dither_Masks() / * 今作るデイザーの色 , 49 : int C010r , フェース・ 1 * / / * テンプレートのマスク番号 , フェース・ 1 * / 50 : mask, / * 1 つのマスク内の i 番目の値 , フェース・ 1 * / 51 : value, C010r ー 1 , / * 最初の色のインデクス , フェース・ 2 * / 52 : C010r ー 2 , / * 2 つ目の色のインデクス , フェース・ 2 * / 53 : / * デイザーテーブルへのインデクスに使う , フェース・ 2 でり 54 : index; 55 : 56 : / * 最初に色集合 1 を作る : これらの色は各色の 2 種類の明度色を足し , 57 : * さらにグレーとホワイトを量を変えて混ぜて作る。 58 : * この方法で 1 4 0 のデイザーができる。 * / 59 : for ( C010r = 1 ; C010r ← 7 ; C010r + + ) 60 : for (mask=0 : mask<=19; sk + + ) 62 : for vaIue=0; vaIue<=3; value + + ) 63 : 64 : switch(dither—template[mask] [value]) 66 : case 1 : dither-masks[mask + (C010rー1)*20] Cvalue] = C010r : 68 : break : case 2 : dither_masks[mask + (C010rー1)*2の Cvalue] = C010r + 8 ; 69 : break; case 3 : dither—masks[mask + (C010rー1)*20] [value] = WHITE—50; 71 : 72 : break; case 4 : dither—masks[mask + (C010rー1)*20] CvaIue] = WHITE—IOO; 73 : 74 : break; default:break; } / * end switch * / } / * end for value * / 77 : / * end for mask * / / * end for C010r * / 80 : 81 : / * 色集合 2 を作る : これらの色は 16 色から 2 色ずつの組み合わせを取り , 82 : * それらを以下の比率でミックスして作る . 83 : * ( 25 % と 75 % ) , ( 50 % と 50 % ) , ( 75 % と 25 % ) 84 : * フェース・ 1 で作ったものが重複してはならない。 * このフェース・で 2 9 4 色ができ , 計 4 3 4 色となる。 * / 85 : 86 : index=140; 88 : for C010r 1 = 1 ; C010r ー 1 ← 14 ; C010r ー 1 + + ) 89 : 90 : for ( C010r 2 = C010r 1 + 1 : C010r 2 ← 15 ; C010r 2 + + ) 91 : 92 : / * この 2 色を前に使ったか調べる * / if ( ! ( C010r 1 + 8 = C010r ー 2 ) ) 93 : 94 : / * 25 % の C010r ー 1 と 75 % の C010r ー 2 * / 95 : 96 : dither masksCindex 0 = C010r ー 1 ; 97 : dither masks index 1 = color 2 : 98 : dither masks index 2 = color 2 ; dither—masks[index] [ 3 ] = C010r ー 2 : 99 : 100 : index 十十 ; 101 : 102 : / * 50 % の C010r ー 1 と 50 % の C010r ー 2 * / 103 : dither masks index 0 = C010r 1 : 104 : dither masks index 1 = C010r 2 : デイザリングを使って色数を増やそう ! 27

10. 月刊 C MAGAZINE 1992年1月号

List 1 181 : 182 : 183 : 184 : 185 : 186 : 187 : 188 : 189 : 190 : 191 : 192 : 193 : 194 : 195 : 196 : 197 : 198 : 199 : 200 : 201 : 202 : 203 : 204 : 206 : 207 : 209 : { 211 : 212 : 213 : 215 : 216 : 217 : 218 : 222 : 223 : 224 : 225 : 226 : 227 : 229 231 : 232 : 234 : 235 : 237 : 238 : 239 : 240 ・ 242 : 243 : 244 : 245 : 247 : 252 : 253 : xl = (int (. 5 + cos(angle)*r); = (int (. 5 + sin(angle)*r); x2 = ー xl : light = base—color + 7*(float) (dx*dx + dy*dy + dz*dz)/(float)norm_factor; lz-z; dz dy = ly-y; ー lx-xl ; dx Z ニ (int) (. 5 + sqrt(xl*xl + y*y)) : for (y=y2; y く =yl; y + + ) if ( 1 ight>=base—color + 8) light = se ー C010r + 7 : Dither 円 ot ( xl + xo , y + yo, light) : = (iFt) (. 5 + sqrt(x2*x2 + y*y)) ; dx = lx-x2; dy = ly-y; レマ ; 1 ight = base-color + 7*(float) (dx*dx + dy*dy + dz*dz)/(float)norm_factor; if ( 1 ight>=base—color + 8) 1 ight = se ー C010r + 7 ; Dither Plot ( x2 + xo , y + yo, light) : / * end for y * / / * end fo 「 angle * / 205 : } / * end sphere * / 208 : Sphere—Demo(int mode) 210 : / * システムを正しいをト・に設定した上で EGA または VGA を m e にして * このルーチンをコールする。 * / int height; 214 : if (mode==EGA) height=175; else height=240; / * 350 の半分 * / / * 480 の半分 * / 219 : / * ューザが何かキーを押すまで球を描く。 * / 220 : srand(13) ; 221 : while(!kbhit()) S ere ( r d ( ) % 320 + 1 , rand()Xheight + 1, rand()X50 + 1, ( r d ( ) % 7 ) * 20 + 1 ) : for (x=0 : x く = 39 : x + + ) 233 : for (y=0 ; y ← 10 ; y + + ) int X, y, C010r = 0 ; 230 : / * 434 色すべてを見せる * / 228 : Palette_Demo() } / * end Sphere—Demo * / main() 236 : } / * end Palette_Demo * / Rectangle(x*8, y*8, x * 8 + 7 , y * 8 + 7 , C010r + + ) : 241 : / * この皿 in ( ) はグラフィクスモードをセットアップしてから , * EGA カードの場合は , 1 6 色 640X350 を意味する定数 ERESCOLOR を用いる。 * グラフィクスは 1 6 色の VGA 640X480 に設定する。 * カラーパレットを見せた後で , 3D の球体を描く。 * デイザリングのデモを行なう。 256 : } / * end main * / 255 : Sphere-Demo(VGA) : 254 : / * 球体を描くデモ * / c I earscreen (—GCLEARSCREEN) ; 251 : getch(); 250 : / * ユーザが色を鑑賞する * / 249 : Palette_Demo() ; 248 : / * 434 色すべてを見せる * / Create_Dither_Masks() : 246 : _setvideomode( VRES16COLOR) : / * EGA を使うなら” VGA ”を” EGA ”に変える * / ラフィックスシテスムて、も使えるて、しよう。 名前がそれぞれ , setcolor, setpixel, s etvideomode, clearscreen という関数カま 必要て、す。 リストを見ただけて、は分かりにくい関数 二つあります。 まず , Create Dither Mask は , 434 色ぜ んぶ用のデイザーマスクを作って , それを dither masks という名のグローノヾルなテー プルに入れます。そのテープルに , 他のす べての関数がアクセスします。 もうーっの関数 , Dither_plot は , このデ イザリングシステムの中核部て、す。これは ( 0 番から 433 番まて、の ) 指定の色を , 解像度 が実際の半分の仮想画面上にプロットしま す。 これらの関数は , 効率の点て、最適化され てはいないのて、 , 注意してください。考え 方をお教えすることが , 目的なのて、す。私 は , アセンプリ言語て、書いたものを使って いますが , C のリストだと , 実際に使うハー ドウェアやソフトウェアの違いを超えて , 原理を示すことがて、きるのて、す。 これらのルーチンを , 楽しんて、ください そして , 手をこまぬいていないて、 , デイザ リングをしましよう ! (Anddon'tjuststa nd there : dither it ! 直訳 : ただじっと 立っていないて、 , 動き回りましよう ! ) 。 〔訳注〕デイザリングは一般的には , 複数 の物理的な画素て、仮想画素を実現する方法 なのて、 , たとえば画面上の形状の輪郭のギ ザギザを一一中間トーンにより ばやか して , 滑らかに見せるためなどにも使われ ている。 Andre Lamothe 氏は , コンピュータ科学と 数学の学士号を有し , 電気工学の修士号目 指して勉強中。彼は目下 , R 旧 C プロセッサ 上のソフトウェア工ンジニアリングに取り 組んでいる。 デイザリングを使って色数を増やそう ! 29