gclconv ver3.0 ( since 1999/06/25 )



$Id: readme.txt,v 1.14 2002/06/05 05:53:38 usr01475 Exp $



--------------------------------------------------------------------

☆ver3.0での新機能

--------------------------------------------------------------------



・サブブロックのサポート(2002/05/20)



記述中に { }によるサブブロックを書けるようになりました。

#defineと組み合わせて、読みやすく書けるかもしれません。

ただ、変数スコープ等にはまったく影響ありません。

あくまで表記上の便法ということです。





・文字列 resource 文字チェック幅指定機能、ヒアドキュメント対応 (2002/05/17)



resource リソース名 -fontcheck 520 120 0 12 0 {

	タグ1: -fontcheck 520 120 0 12 0 {

		文字列...		

I	}

	タグ２: <<- EOF

shell, perlのHereDocument風の文字列。空白や改行もそのまま渡される。

行末の空白だけは自動的に削られる。

終了は、<< で指定したワードが先頭にあるときのみ。それ以外は

認識しないので、注意すること。

<<-ではじめると、改行コードを無視し、完全に連続した文字列になる。

EOF

	タグ３:

		....

}



文字列リソースの描画フローチェックを各リソースごとに指定することが

出来るようになりました。



-fontcheckは省略可能です。５つのパラメータは順に 

width, height, chara_skip, line_skip, flag　をあらわします。

flagが1の場合は、禁則を行わない。(日本語以外)



おそらく、数種類しかないでしょうから、

defineを使って、

#define TITLE_FONT_AREA	-fontcheck 520 120 0 12 0 

とかやっておいて、それを使うほうがいいと思います。



リソース名の場所とタグの場所の両方にあった場合は、タグの方の指定が

優先されます。



shell/perlライクなヒアドキュメントも実装しました。上の例の中の文書を

参考にしてください。



・emacs, Hidemaru用TAGファイル作成(2002/05/15)



gcltags.plというperlスクリプトで、emacs用とHidemaru用のTAGSを作成できる

ようになりました。



emacs/muleの場合は、M-. で下に検索したいシンボルを入れると、その定義位置に

飛びます。C-u M-.で、その次の定義位置に行きます。



Hidemaruの場合は、hm_gcltags.macというマクロを作成しましたので、

それを任意のキーで呼び出せるよう設定してください。

マウスで選択した文字列をキーにして検索してタグジャンプします。



・sed的プリプロセッサ(2002/05/15)



#define で定義した式に対してsedっぽい正規表現（厳密にはPOSIX拡張正規表現)

をつかって展開時に置換を行うことが出来ます。



これを使うと、



#define SET_ENEMY chara 敵兵 敵:ENEMY_NO -p ENEMY_POS



d:SET_ENEMY( "/ENEMY_NO/01/", "/ENEMY_POS/100,100,100/" );

のようなことを行えます。



正規表現を使うと、



d:SET_ENEMY( "/:([^_]+)_NO/\1:10/" );



みたいな感じでしょうか。$1ではなく、\1で展開されることに注意してください。

置換部分のメタ文字は\だけです。

()による部分文字列の展開は８こまでです。

検索部で使える正規表現演算子(メタキャラクタ)は(多分)以下の通りです。

[= =] {: :} [. .] [ ] ( ) * + ? {n ,m} ^ $ | . 

perl拡張の\dとかは使えません。[:digit:]とかになります。

詳しくは、http://www.kt.rim.or.jp/~kbk/regex/regex.htmlとかで、

「POSIX拡張正規表現」を見るといいでしょう。



ただし、これはあくまでもインライン展開ですので、多用すると

gclのサイズが際限なく大きくなっていきます。

また、あとで読みにくくなりますので、あまり技巧的なことをしないように

心がけてください。



・即時実行型ブロック (2002/05/07)



command.defの宣言中で、{ imm ... } という形式で宣言されたブロックは

即時実行型（関数がコールされているなかで実行される)扱いになり、

if, switchなどのブロックと同様、その上のスコープの引数、変数を参照

できるようになります。



当然、そのブロックを呼び出すときに新たな引数は設定できません。



この機能を使うときは、プログラム側では、ブロックを

GCL_ExecBlock( top, NULL );

で呼び出す必要があります。

Actなど、gclから直接呼び出されない関数の中から呼び出すと、引数やローカル変数を

参照した時点でASSERTで落ちます。



・文中での式	(2002/05/07)



式をeval()を使わなくても書けるようになりました。



proc test {

	local $$:local;



	$$:local = 128;

	( $$:local = 128 );



	;

}



のように書けます。

文の先頭が'$'または'('で始まっている場合、式として解釈します。

式の評価が終わったあとは、$statusにはその式の値が代入されます。



eval()に比べて、こちらで書いたほうが、式１つにつき約６バイト程度節約できます。

()が一番外側につく分にはデータ量の増減はありません。



chara等のパラメータとして与える式については、今まで通り()が必要です。



・switch文の新設	(2002/05/07)



以下のような形式でswitch文を書けます。



switch ( 式 ) {

	case ( 式 ) {

		;

	}

	case ( 式 ) {

		;

	}

	case ( 式 ) {

		;

	}

	default {

		;

	}

}



defaultはなくてもいいですが、必ず最後に書く必要があります。それ以降のcaseが

あっても実行しません。

( 式 )は、定数でなくても問題ありません。

switch(式) == case(式) が成立する場合に、そのブロックを実行します。

switch(式)を１回だけ評価した後、上から順番にcase(式)を評価し、

値が同じであれば、そのブロックを実行します。

どれか１つのブロックが実行されたら、switch文から抜けます。



・proc引数と、call文



procやcharaの引数として、proc名を渡すことが出来ます。

p:proc名という形で渡してください。

渡された引数はcall文で呼び出すことが出来ます。



proc test $:param {

	;

}



proc test2 $:proc $:param1 {

	call $:proc $:param1;

}



@test2 p:test 100;



みたいなことが出来ます。

この場合、testは参照されたことになり、gcx中に含まれることは保証されます。



式の中では、p:形式は使えません。

パラメータを介すれば変数にproc名を入れることは出来ますが、

ステージをまたいで呼び出しなどが発生すると、不具合が起こることが予想されます。

くれぐれも慎重に使用してください。



・ステージローカル変数	(2002/05/03)



$$w:変数名 のような形式で、ローカル変数を記述できるようになりました。

各gclのレベル(正確にはgco,gcxレベル）でローカルな変数です。

基本的にステージが変わったときには０クリアされます。

リスタート時にも０クリアされます。

（０クリアのタイミング自体は実装依存）

ほかはまったく普通の変数と同様に使えます。

gclk実行時にパラメータでローカル変数バッファのサイズを指定してください。

gclkはリンクしたすべてのgcxでのローカル変数バッファの最大使用量を出力します。



・proc内ローカル変数	(2002/05/02)



procの中で、localタグで指定したローカル変数を使えるようになりました。

そのprocの中だけで有効です。



proc test {

	local $$:test

	eval( $$:test = 100 )

	:(略)

}



形式は$$:変数名です。proc引数と違い、代入もできます。



引数スタックを使用するので、呼び出されているすべてのprocの

(引数の数+1)+(ローカル変数の数)の総和には実装側での制限があります。

（MGS2の場合は64個）

localは必ずしも先頭に書く必要はないですが、使用する前に宣言する必要はあります。

初期化時に０クリアは行われません。

また、ifブロック等の中でlocalで宣言しても、そのprocの中だけで有効です。



proc引数と同様、chara,trapなどのパラメータの実行ブロック中で使うことは出来ません。



・バイナリエンコード形式の変更	(2002/04/27)



バイナリフォーマットを変更し、ブロックサイズの記述部を可変長にしました。

また、小さい定数の扱いが変わっています。

実行用のバイナリサイズが小さくなりました。

これにより、ver2.0系とのバイナリレベルの互換はなくなりました。



・PROCテーブル,CHARAテーブルのソート	(2002/04/27)



PROCテーブルにおいても、charaテーブルと同様、ID順にソートされて

出力されるようになりました。検索時にbsearchを使うことが出来ます。



--------------------------------------------------------------------

☆ver2.0での新機能

--------------------------------------------------------------------



・プロトタイプ宣言での省略可能記法



mesg スネーク $s:名前 command[1] $w:パラメータ１ [ $w:パラメータ2 $w:パラメータ3 ]

のように書くと、[]内のパラメータは省略可能になります。



・extern 宣言文



extern chara キャラ名

を使うことで、stage/*.cのキャラリスト出力にそのキャラを含むことが出来ます。



・リソーステーブル



resource リソース名 {

	タグ1:

		$i:{

			{ 0, 1, 2, 3, 4 },

			{ 0, 1, 2, 3, 5 },

		},

	タグ2:

		'文字列',

	タグ3: {

		文字列。先頭の空白は無視される。

		行途中の半角空白はいくら連続していても1つとして扱われる。

	},

};



のような形式でリソースを宣言できる。

バイナリブロックと文字列ブロックの2種類が可能。

参照は、[リソース名:タグ名]の形で行なう。[:]はすべて半角。

command.def上では'...'の文字列型か、$d:という形式で宣言できる。



バイナリ形式では以下の型で宣言可能。

$b:, $w:, $i:, $s:, $t:, $v:



プログラムからはデータのサイズは取得できないので、

ターミネーターなどが必要になる。

{}のネストは、表記をわかりやすくするために使える。

データの構造とは無関係。



$*:で宣言するとgclのデータフォーマットで格納される。

終端には、GCL_ENDがつくので、プログラムからは、NextStrで判別できる。



文字列は1つのタグに複数設定できるが(一連の文字列として扱う)

バイナリは1つのタグにたいして1つのブロック。



procなどと同じように、参照されなかったデータは

バイナリの中に含まれないので、ライブラリ的な扱いができる。



・外部関数定義の読み込み



command.defで、以下のような定義を行なうと、

-mオプションでステージの関数リストを作成する時に

その名前の, ID, 関数名を記述したリストファイルを読み込み、

関数リストに加える機能を追加。（デモエフェクト用）



command demo $E:symbol		// t:シンボル扱い

command demo 'Extern'		// 文字列扱い



シナリオ中、

command demo 's01a0d0'

で、s01a0d0.lstを読み込む。( -l optionで検索パスを指定可能）



*.lstは、

------

0x01000001	NewDemoEffect1 デモエフェクト

------

のような３コラムを持つEUCテキストファイル。



・command.defプロトタイプでのオプション文字の指定の拡張



-opTion など、間に大文字をはさむことでその大文字をオプション文字として

扱うことができる。



・command.defプロトタイプでのブロック引数のエイリアス機能



command.def 中での、{ }実行ブロック宣言中に$:で変数名を列挙することで、

実行ブロック中での$1などの引数のエイリアスとして扱うことができる。



・プログラムへの変数の参照渡し( 1999/12/10 追加 )



$r:変数名 でプロトタイプ宣言することで、プログラムへ参照渡しすることができます。

呼び出し側では、変数名か、配列名[offset]を書いて下さい。

offsetを指定することで、プログラムから見えるアドレスをずらすことができます。



・proc, command の返り値( 1999/12/10 追加 )



proc 内から return で返り値を返せます。

返り値は $status または $? で参照できます。

command コマンドで起動したキャラ関数の返り値も

同じ場所に入ります。



proc test {

	if( $1 == 1 ){

		return 1;

	} else {

		return 2;

	}

}



returnなしでprocが終了した場合、返り値は

「一番最後に評価された式の値」

になります。（以下の＜式の中のコマンド＞参照）(00/02/14修正)



return のみが書いてあった場合は、返り値は０になります。



プログラムからは、

GCL_ExecProc の返り値として、シナリオでの返り値を参照できます。

GCL_ExecBlock の場合は、返り値は返しませんが、

グローバル変数の GCL_Statusを見れば、返り値を取得できます。



・式の中のコマンド( 1999/12/10 追加 )



式のなかで、`コマンド`を呼び出し、その返り値を値として

用いることができます。

シングルコーテーションではない(シェルスクリプトのコマンド呼び出しと同じ)

ので注意して下さい。

`コマンド`は、入れ子にはできません。

式扱いですので、必ず ( ) で囲む必要があります。



返り値を返さないコマンドを入れても、０が返ってくるだけです。



返り値を返すコマンドは、現在のところ、

proc呼び出しでのreturn

evalの値

command コマンド

のみです。



if( `@proc 1` == 1 ){

	:

}



if( `command スネーク位置検査 -p 100 100 100` == 1 ){

}



eval( $f:フラグ = `@proc 1` );



chara hohoho name -f ( `@proc $2` )



など。



ただし、式のデータの最大長は「呼び出すコマンドの変換後のデータ列も含めて」

255バイトですので、それを越えると、エラーになります。(2002/05/07この制限はなくなりました)

コマンドが長い場合は、proc呼び出しに変更して下さい。



・プリプロセッサの導入



#if, #ifdef #else if, #else, #endif が使用可能。

define, include が、#define, #include に変更。

これにともない、行コメントが # から // に変更。



gclconv に -D オプションを作成しました。

gclconv -D TEST

または、

gclconv -DTEST=1

のような形式が使えます。(99/11/15)



・型の拡張



32Bit int型変数を新設しました。

    $i:変数 

で記述します。以前のバージョンでの$l:は64Bit long と紛らわしいのでやめました。

浮動小数点数は扱いません。



また、$s:文字コードが、32ビットに拡張されました。(99/10/05 24->32)

また、PROC IDは２４ビットになっています。



プログラマは、今までのプログラムを再利用する場合、文字コード、

PROC IDを記録していた変数がshort のままだと誤動作しますので、注意してください。



・文字列ID(99/10/05 add)



24Bit + 8Bit で32ビットとして扱えます。

文字列IDそのものは24ビットですが、それに8ビットの数字を付加することができます。

記述は、空白を開けずに、:で区切って、name:01のように記述します。

内部的には、( 数字<<24 ) | ( 文字列ID )という形で持っています。



・論理シフト(99/10/05 add)



<<, >> で論理シフトを行います。算術シフトではありませんので、

符合ビットは保存されません。



・シナリオリンク変数



$i:型も使用できるようになりました。

ただし、上から順に積めていくので、アライメントで無駄が出ないように

記述順番を考えてください。



・配列の新設



すべての型の変数に[]で添字を与えることで配列を記述できます。

配列を使用する前には、dim 命令で最大要素数を指定する必要があります。

    例) dim $f:アイテム設置[ 128 ];

dim命令はその変数を使うすべてのgclに必要です。(.hで#includeするべき)

配列の要素数が変わった場合は変数テーブルを書き換え、以前のセーブデータを

使用できなくする必要があります。（後述）

当然、セーブされる容量が大きくなりますので、配列の乱用には充分注意する

ようにしてください。

参照する[]の中にはもちろん変数を使った式も使用可能です。



・変数バッファのバージョン管理



変数バッファの記録ファイルである variable.symに作成日の情報を埋め込むように

しました。それをgcx内に記録し、メモリーカードにセーブするときにその情報も

セーブすることで、そのセーブファイルが現在使用可能かどうかを判定することが

できます。

gclconv,gclkは、以下の場合にvariable.symの作り直しを要求します。



    以前と同じ名前で型の違う変数を検出したとき

    配列の添字の最大数が変化したとき

    リンク変数（プログラムから読み取り可能な変数）の数が変化したとき

    gclkの内部バージョンが変更されたとき (99/10/05 add)



この場合は、variable.symを消して、作り直してください。その時点でその前の

セーブファイルは使用不可になります。

また、変数の追加は問題ありませんが、

    初期値が０以外であることが必要な変数が追加された

などで、以前のセーブファイルでの動作がおかしくなるときは、

gclconv, gclk側では検出できませんので、明示的にvariable.symを消して、

以前のセーブファイルを使用不可にしてください。



・stage/*.c ファイルの自動生成



command.defの書式に、関数名を記述するように変更しました。キャラクタ名の後に

[]で囲んだCの関数名を記述します。

    chara スネーク[NewSnake] $s:名前 -p $v:初期位置 ...

これにより、gclconv <gcl> -m <path>で、そのgclでコールされている

すべてのcharaのテーブルを持つ.c を自動生成します。

自動生成元のファイルは_base.cで、これはgclconvをかけるディレクトリ(scnなど)に

おいておく必要があります。すでに<path>にファイルができている場合は、

そのファイルを修正しに行きます。触るのは

/* gcl chara */ から /* gcl chara end */

までの行だけです。

extern 指定も勝手にやってくれますので、main/*.hsの作成は必要なくなりました。



・mesg プロトタイプ



mesgコマンドの記述を以下のように変更しました。

    mesg キャラクタ名 名前 コマンド [引数] ...

たとえば、今までの

    mesg snake motion 0

は、以下のようになります。

    mesg スネーク snake motion 0

また、mesgコマンドも、各キャラクタごとに command.def でプロトタイプ宣言を

必要とするように変更しました。

存在チェックを行いますので、必ずchara定義の後で宣言してください。

    例) mesg スネーク $s:キャラ名 コマンド[1] $w:引数１

これにより、引数の型と数をチェックすることができます。

コマンドに[]で数字をつけると、プログラムにコマンドがその数字で送られます。

つけないとコマンドの文字列コードになりますが、できるだけ数字を指定するように

してください。

0、0x000100以降はシステムで予約(kill, mapなど)しますので、

コマンドはそれ以外の値を使用してください。



・文字列IDチェックの強化



chara, mesgプロトタイプで $s:テクスチャ名 のような宣言が行われた場合、

その宣言名（この場合は「テクスチャ名」）で指定された引数すべてに対して、

同一IDチェック（違う文字列で同じIDがないかどうか）を行います。

＃したがって、プログラマはchara 定義で少し考慮してもらう必要があります。



・group 形式による存在チェック



上のcharaプロトタイプと同じですが、$s:テクスチャ名 などで共通に宣言された

引数に関して、

    group テクスチャ名 {

        stage_tex_01,

        stage_tex_02,

        stage_tex_03,

        stage_tex_04,

        stage_tex_05,

        lamp_tex01,

        lamp_tex02,

    };

という宣言を行うことで、この中に宣言された以外の引数を取ることを禁止することが

できます。用途としては、テクスチャ名やモーション名などに使えるでしょう。

groupタグをツールで作成して、それをシナリオに張り付けるだけで、ステージにない

テクスチャを指定していないかチェックすることができます。



・enum 形式



数え上げ定数シンボルを定義できます。使用用途としては、上のgroupと同じく、

モーションリスト等を想定しています。たとえば、モーション番号をモーション名と

して記述できるようになります。

    enum 敵兵モーション {

        motion_stg01_standup = 0,

        motion_stg01_fuse,

        motion_stg01_kaidanup,

        motion_stg01_kaidandown,

    };

これも、ツールの方で作成したリストを張り付けることが前提です。

なお、参照側では、以下のようにして参照してください。

    d:敵兵モーション:motion_stg01_standup

内部処理がよく判る、非常に美しい書き方です。C++みたいですね。

スペースを入れないでください。全部で128文字を越えてもだめです。

これで、同じモーション名でも各々違う番号として参照が可能です。

groupは文字列ID、enumは数え上げ定数です。



・オプション、シナリオの最大数の制限



オプションの長さ、シナリオ、PROCの長さがそれぞれ、16Bit, 32Bit, 32Bitに

拡張されています。



・式



定数など、先に計算できるものは計算しておくようになりました。

引数などで、

-f ( 0x8 | 0x4 )

とすると、ちゃんと0xCが渡されます。定数を扱えるところすべてで使用することが

できますが、式は（）で囲ってください。



☆プログラムインターフェース



上にも書きましたが、command.defに記述することで、*.hsなどは必要なくなっています。

その分、command.def が肥大化することが考えられますので、将来的にcommand.def 内で

各人担当分のdefを#include でまとめるようにします。



chara コマンドの各キャラクタのプログラムの引数は、いままで



void *NewSnake( int argc, char *argv[], int name, int where )

{

}



でしたが、新バージョンでは、



void *NewSnake( int name, int where )

{

}



に統一します。name にはシナリオから渡される名前の文字列IDが、whereには

シナリオ起動時のマップIDが渡されます。



command コマンドが新設されました。

これのプログラムの引数は、

int NewCommand( void )

{

}

になります。返り値が、$status, $?に入ります。





--------------------------------------------------------------------

☆簡単な文法仕様

--------------------------------------------------------------------



・パース



基本は１行１命令

// ...,  /* ... */はコメント

\で次の行に送る



#if, #else, #endif サポート



・疑似命令



#define A B

参照時には d:Aという表記をおこなう。



#include ".."



・型



$i:32ビット数値

$w:16ビット数値(符合付き)

$b:8ビット符合なし

$f:1ビットフラグ



$v:32ビットベクトル     x, y, z   コンマ区切り数値 (コンマの前後の空白は無視)



$s:24ビット文字コード       (GV_StrCodeと同じエンコードで、文字列を数値化する）

    string:01   で上位８ビットが0x01の３２ビットコードを表現できる。



文字列



・うち、変数



32ビット数値(符合付き)  $i:変数名

16ビット数値(符合付き)  $w:変数名

8ビット符合なし         $b:変数名

8ビット文字             $c:変数名

1ビットフラグ           $f:変数名



24+8ビット文字コード    $s:変数名

(GV_StrCodeと同じエンコードで、文字列を数値化する）



ユーザー関数ID          $p:関数名       定義フォーマットのみ使用。

32ビットベクトル        $v:変数名       定義フォーマットのみ使用。

変数参照型				$r:変数			定義フォーマットのみ使用。



Tsymbol 定義フォーマットのみ使用。

見つからなければ０扱い  $t:シンボル

見つからなければ-1扱い  $T:シンボル		ワーニングを出力

見つからなければエラー	$C:シンボル



変数名は、バイナリにコンバートされるとき、変数バッファの位置情報に変換される。



・式



式は、逆ポーランド記法のバイナリデータとして格納。

実行時に計算。

つねに()で囲む。



・基本コマンド



■proc 関数名 ｛ 実行ブロック ｝

呼出は

@関数名 引数１ 引数2 ...

引数は実行ブロック内で $1 $2 $3...という名前で参照される。



proc 関数名 $:引数1 $:引数2 $:引数3 {

}



という形式もありで、この場合引数を

$:引数1 という形で参照できる。(推奨)



■if 条件式 { 実行ブロック } else if { } else { 実行ブロック }

ただし、 パーサーの都合で、

if(  ) command はつかえない。

else, else if は、 } に続けて（改行しないで）記述する必要がある。



■return [返り値] 実行ブロックの強制終了





・拡張コマンド



command [ パラメータ ]... [ スイッチ ] [ パラメータ ] ...



スイッチは-で始まり、その直後の英字1文字で区別される。

英字1文字以降の文字はつけてもいいが、無視。



---- コマンド記述ファイル ----



command.def



以下のようなフォーマットで記述する。

文字列は""でくるむ。実行ブロックは{}でくるむ。

-で始まる文字列、もしくは何もつけない文字列はオプション指定と見なされる。

...は直前の繰り返し。*は何でもいい。

(実際のプログラム中では、すべてshortとして取り出される)

ファイル名も基本的にはIDで呼び出される。

コンパイル時に型チェックするので、プログラム側では型チェックは原則不要。



//光源指定



light -dir $v:光源方向 -col $v:色ベクトル -amb $v:環境光



//カメラ設定



camera -bound $v:右上角 $v:左下角 -track $w:引きサイズ



//マップ指定



map -define $s:マップ名 $s:ファイル名 \

    -show   $s:マップ名 \

    -about  $s:マップ名



trap $s:トラップ名 $s:キャラ名 $s:イベント種別 { 実行ブロック }



mesg $s:キャラ名 $s:メッセージ * ...



//不定数引数がその前の3つのリピートだったら、

// -p $i:引数１ $w:引数２ $b:引数３ ...3

//みたいな書き方もできる。



//不定数引数の ...を指定したオプションの後に、別のオプションをつけるときは、

//呼出し側の不定数引数全体を { ... }で囲むこと。



//#キャラ記述



chara 巡回兵 $s:名前 -i $b:ID番号 -b $s:血液型 



//#コマンド記述



command sound -x $i:サウンドコード



などなど。



