このページの元はKAODUNのhikiのページです。wiki形式に変換して使用しているものです。
コメントを追加する場合、wikiとhikiとの形式の違いに注意してください。自動的にwikiの形式へ変換されたりしません。


グラフィックシステムライブラリ  

汎用のゲーム向けグラフィックドライバ開発のためのページです。


開発スレッド - 聖人 (2005-03-20 (日) 22:41:36)  

掲示板の「グラフィックドライバ」スレッドの続きです。

  • 2005-03-20 (日) 22:50:26 聖人 : (パターンのサイズ定義の件)すみません、分かりにくい状態になっていました。BG画面のパターンサイズは描画時に最初に描画するパターンのサイズに合わせてしまおうと思って構造体を作ったのですが…。ということで、BG画面ごとにループを回す方でお願いします。
  • 2005-03-20 (日) 22:57:53 聖人 : (パレットの件)画面毎に仕様を変えたのは、ずばり肥大化しそうだったからです。あと、最初に書かれた通り、パレット番号を一カ所変えるだけで衣替え出来るというのもあります。もし16色で足らないような絵であればピクセルモードで自力描画をしてください、という方針のつもりです。ということで、このままお願いします。
  • 2005-03-20 (日) 23:04:59 聖人 : (drawptrnの件)しまった、tmは公開している版には含まれていないやつですね。すみません。こいつの部分を上げておきます。名称変更したほうのtと指定がないやつは、指摘の通りピクセルモード向きの描画関数のつもりです。gのやつはdrawpatternのtに相当するもので、こいつは名前が変わっただけです。BGやスプライトの描画にはこいつだけで用が足りるはずなので、そのまま使ってください。
    /*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
    	パターン表示(8 * 8 dot,透過表示,メモリ)*/
    void drawpattern_8tm(unsigned short *dest, int x, int y, int width, unsigned char *src)
    {
    	int cx, cy;
    	unsigned int dat;
    
    	/* 転送先メモリに転送 */
    	dest += y * width + x;
    
    	for(cy = 0; cy < 8; cy++){
    		for(cx = 0; cx < 8; cx += 2){
    			
    			dat = pal[*src].c;
    			if (!(*src & 0x0F)){
    				dat &= 0xFFFF0000;
    				dat |= (*((unsigned int *)dest) & 0x0000FFFF);
    			}
    			if (!(*src & 0xF0)){
    				dat &= 0x0000FFFF;
    				dat |= (*((unsigned int *)dest) & 0xFFFF0000);
    			}
    			*((unsigned int *)dest) = dat;
    			src++;
    			dest += 2;
    		
    		}
    
    		dest += width - cx;
    	}
    
    }
    
  • 2005-03-21 (月) 09:28:29 くーみん : 了解しました、とりあえずこういうソースを高速化すればいいのかな…というのをあげておきます、スプライトはまだ積んでませんが。
    #include <gsl.h>
    #define EACH_SCR
    /*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
    描画 */
    void gsl_draw(void)
    {
    	int i;
    	#if defined(BLOCK_32)
    	/* BG画面の最大番号から描画 */
    	gsl_sysp->bg->
    	gsl_sysp->bg_count
    	/* スプライトのプライオリティで指定された深度に達したらスプライトを描画 */
    	//#elif defined(EACH_SCR)
    	#else
    	/* BG画面の最大番号から描画 */
    	for(i = gsl_sysp->bg_count - 1;i>=0;i++){
    		/* スプライトのプライオリティで指定された深度に達したらスプライトを描画 */
    		if(gsl_sysp->spr->priority == i)
    			gsl_drawspr();
    		gsl_drawbg(i);
    	}
    	#endif
    	/* モザイクの度合いが指定されていればモザイク化 */
    	/* 暗さが設定されていれば暗くする */
    	/* グラフィックボックスのフラッシュはしない */
    	return;
    }
    /* 分かりやすくするために、関数を分けた、統合しても良い */
    void gsl_drawspr()
    {
    	return;
    }
    void gsl_drawbg(int bgnum)
    {
    	int i,j;
    	if(gsl_sysp->bg[bgnum].mode == 0){/* tile */
    		/* 仮組み,ループ回すには諸変数(特に内側)をローカルのレジスタで持つ方がはやいけど */
    		if(gsl_sysp->ptrn->size==1){
    			for(i=0;i*8< gsl_sysp->v_hight;i++){
    				for(j=0;j*8< gsl_sysp->v_width;j++){
    					drawpattern_8g(gsl_sysp->bg[bgnum].x+j*8, gsl_sysp->bg[bgnum].y+i*8,
    					 gsl_sysp->bg[bgnum].tile[(i*bg[bgnum].x+j*16)*16]);
    					/* (i*bg[bgnum].x+j*8)*8 = (i*(bg[bgnum].x/8)+j)*8*8 */
    				}
    			}
    		}else if(gsl_sysp->ptrn->size==2){
    			for(i=0;i*16< gsl_sysp->v_hight;i++){
    				for(j=0;j*16< gsl_sysp->v_width;j++){
    					drawpattern_16g(gsl_sysp->bg[bgnum].x+j*16, gsl_sysp->bg[bgnum].y+i*16,
    					 gsl_sysp->bg[bgnum].tile[(i*bg[bgnum].x+j*16)*16]);
    					/* (i*bg[bgnum].x+j*16)*16 = (i*(bg[bgnum].x/16)+j)*16*16 */
    				}
    			}
    		}else if(gsl_sysp->ptrn->size==3){
    			for(i=0;i*32< gsl_sysp->v_hight;i++){
    				for(j=0;j*32< gsl_sysp->v_width;j++){
    					drawpattern_32g(gsl_sysp->bg[bgnum].x+j*32, gsl_sysp->bg[bgnum].y+i*32,
    					 gsl_sysp->bg[bgnum].tile[(i*bg[bgnum].x+j*32)*32]);
    					/* (i*bg[bgnum].x+j*32)*32 = (i*(bg[bgnum].x/32)+j)*32*32 */
    				}
    			}
    			
    		}
    	}else{/* if mode==1,pixel */
    		unsigned short *p;
    		p = gsl_sysp->bg[bgnum].y * gsl_sysp->width + gsl_sysp->bg[bgnum].x + (unsigned short *) ((char *) gsl_sysp->gbox + 64);
    		for(i=0; i< gsl_sysp->v_hight;i++){
    			for(j=0;j< gsl_sysp->v_width;j++){/* jをうまくやれば、pix[j]が可能(今はやらない) */
    				*p=gsl_sysp->bg[bgnum].pixel[i*gsl_sysp->v_width+j];/* hightはwidthの間違いでした */
    				p++;
    			}
    			p+=(short *)gsl_sysp->width;
    		}
    	}
    	return;
    }
    
  • 2005-03-22 (火) 13:16:23 聖人 : どうもありがとうございます。描画部分を分けたのは見やすくていい感じです。それに速度が気になるときはインラインにすればいいことですし。この調子でお願いします。
  • 2005-03-23 (水) 12:10:01 くーみん : 3日ほど出かけます。4月入るまでになるべく進みたいです。暗くする所は、色情報毎にテーブルを使って浮動点で掛け算するか、一度変数に入れて、掛け算と割り算すればいいのかな。(32-指定値)/32 ((32-指定値)>>5)まとめてやると桁落ちするんですが、いい方法ないかなぁ。
  • 2005-03-23 (水) 13:42:08 くーみん : なんか間違ってる事いった気がする。そうか、各々の色は高々16,32までの値しか持たないから、引き算で近似するのでも済むのかな、さすがにひどいか…暗くするだけでなくて明るくするのも付けてあげるといいかも。こういうのの高速化は先人の知恵を借りるのが吉なんですが、例えば、homepage1.nifty.com/herumi/adv/adv40.htmlとかね…(光成滋生さん,フラクタルデモ書いた人です)
  • 2005-03-23 (水) 18:21:09 聖人 : 了解しました。>3日ほど出かけます kaodunでは暗くする処理を引き算でやってました(汗。FPUが無い機械でも使うことを想定して、浮動小数点演算は使わないでほしいです。明るくする処理というのは案外あると便利かも知れませんね。ということでGSL_SYSTEMのfadeをsigned charにして、-1~-31の範囲で明るくするようにお願いします。光成滋生さんのページは以前読みましたが、とても自分がついて行けるレベルではありませんでした(滝汗。もっと修行せねば…。
  • 2005-03-27 (日) 21:17:18 くーみん : fadeはこんな感じかな…1だけ変更ならば、高速化できるんですけど、構造体とどっちがはやいんでしょうね。draw_sprはdraw_bgをそのまま移せばいいのでまだです。ちょっと分からなくなってきた所があります。GSL_SYSTEMに、widthとv_widthがあるのはいいんですが、GSL_BGSCREENにx,yがスクリーン別にあるということは、左上からのbg画面と、真ん中辺りからのbg画面があってもいいということですか?あと、どこかで画面をクリアしないと、前の画面が残ったりしないんだろうか…前よりはだいぶ高速になったと思います(未コンパイル)あっぷします。ちなみに聖人さんはどのぐらい手をつける予定でしょうか。
    	if(gsl_sysp->fade!=0)
    		gsl_fader();
    を追加、
    void gsl_drawbg(int bgnum)
    {
    	unsigned int i,j;
    	register unsigned int i_max=gsl_sysp->v_hight,j_max=gsl_sysp->v_width;
    	register unsigned int* tile;
    	if(gsl_sysp->bg[bgnum].mode == 0){/* tile */
    		i_max+=gsl_sysp->bg[bgnum].y;
    		j_max+=gsl_sysp->bg[bgnum].x;
    		if(gsl_sysp->ptrn->size==1){
    			for(i=gsl_sysp->bg[bgnum].y;i< i_max;i+=8){
    				tile=(i-gsl_sysp->bg[bgnum].y)*gsl_sysp->bg[bgnum].x;
    				for(j=gsl_sysp->bg[bgnum].x;j< j_max;j+=8){
    					drawpattern_8g(j, i, tile);
    					/* i,j が0から1刻みならば */
    					/* (i*bg[bgnum].x+j*8)*8 = (i*(bg[bgnum].x/8)+j)*8*8 */
    					/* i,j を8倍すると、(i*bg[bgnum].x+j*8) */
    					/* gsl_sysp->bg[bgnum].tile[(i*gsl_sysp->bg[bgnum].x+j*8)] */
    					tile+=8*8;
    				}
    			}
    		}else if(gsl_sysp->ptrn->size==2){
    			for(i=gsl_sysp->bg[bgnum].y;i< i_max;i+=16){
    				for(j=gsl_sysp->bg[bgnum].x;j< j_max;j+=16){
    					drawpattern_16g( j, i, tile);
    					tile+=16*16;
    				}
    			}
    		}else if(gsl_sysp->ptrn->size==3){
    			for(i=gsl_sysp->bg[bgnum].y;i< i_max;i+=32){
    				for(j=gsl_sysp->bg[bgnum].x;j< j_max;j+=32){
    					drawpattern_32g( j, i, tile);
    					tile+=32*32;
    				}
    			}
    			
    		}
    	}else{/* if mode==1,pixel */
    		unsigned short *p;
    		p = gsl_sysp->bg[bgnum].y * gsl_sysp->width + gsl_sysp->bg[bgnum].x + (unsigned short *) ((char *) gsl_sysp->gbox + 64);
    		for(i=0; i< i_max;i++){
    			int diff=(gsl_sysp->bg[bgnum].pixel+(i*gsl_sysp->v_width))-p;
    			unsigned short *endp=p+j_max;
    			for(;p< endp;p++){
    				*p=*(p+diff);
    				p++;
    			}
    			p+=(short *)(gsl_sysp->width-gsl_sysp->v_width);
    		}
    	}
    	return;
    }
     
    #if (!defined(MASK_COL16))
    #define MASK_COL16 0x0821
    //0b00001000 00100001
    #define MASK_COL16_WIT 0xffdf
    //0b11111111 11011111
    #define MASK_COL16_BLK 0x0020
    //0b00000000 00100000
    #define maskB(x) ( (x) & 0x1f )
    #define maskG(x) ( ( (x) & ( 0x3f << 5 ) ) >> 5 )
    #define maskR(x) ( ( (x) & ( 0x1f <<11 ) ) >>11 )
    #endif
    /* 呼ばれたときはgsl_sysp->fade!=0 */
    void gsl_fader()
    {
    	unsigned short *p=(unsigned short *) ((char *) gsl_sysp->gbox + 64),endp;
    	signed short fade =gsl_sysp->fade;
    	char r,g,b;
    	unsigned int temp;
    	endp=p+gsl_sysp->width*gsl_sysp->height;
    	/* 構造体作るのとどっちがいいのか… */
    	if(fade>0){
    		for(;p<endp;p++){
    			temp=*p;
    			r=maskR(temp);g=maskG(temp);b=maskB(temp);
    			r-=fade;
    			if(r<0)
    				r=0;
    			g-=fade*2;
    			if(g<0)
    				g=0;
    			b-=fade;
    			if(b<0)
    				b=0;
    			temp = ( r << 11 ) | ( g << 5 ) | b;
    			if(temp==MASK_COL16_WIT)
    				temp=0xffff;
    			if(temp==MASK_COL16_BLK)
    				temp=0;
    			*p=temp;
    		}
    	}else{
    		fade-=fade;
    		for(;p<endp;p++){
    			temp=*p;
    			r=maskR(temp);g=maskG(temp);b=maskB(temp);
    			r+=fade;
    			if(r>0x1f)
    				r=0x1f;
    			g+=fade*2;
    			if(g>0x3f)
    				g=0x3f;
    			b+=fade;
    			if(b>0x1f)
    				b=0x1f;
    			temp = ( r << 11 ) | ( g << 5 ) | b;
    			if(temp==MASK_COL16_WIT)
    				temp=0xffff;
    			if(temp==MASK_COL16_BLK)
    				temp=0;
    			*p=temp;
    		}
    	}
    	return;
    }
  • 2005-03-28 (月) 22:57:05 聖人 : すみません、返事が遅くなりました。どうもありがとうございます。構造体で書いても結局コンパイル時に同じように直されてしまうとおもうので、このままでいいんじゃないかと思います。BG画面に関してはそういうイメージでOKです。ただしプラスの座標を持つ場合に下記のようになるようにお願いします。あと画面のクリアはしなくていいです。最下位置の画面が実画面全面に描画されればクリアの必要は無いと思うので。手を着ける量は未定です…。後から思いつきで細部を弄る可能性はありますが…。
  • 2005-03-29 (火) 16:59:08 くーみん : drawptrnにある、pal[*padr].cという表現はなにで代わればよいのだろう…多分gsl_sysp->pal[なんか].n[*padr].uだから、今使ってるパレットを指定したいのです。引数増やせばOKですか?あと、上のものはコンパイルしてみた所、…int* tileがcharの、endpが*endpの間違いでした。スプライトは書いておきます、あと、モザイクの仕様ですね。でもって、半透明の所をさくっと導入、と。
    void gsl_drawspr()
    {
    	int i=0,i_max=gsl_sysp->spr->max_spr;
    	struct GSL_SPRITE *sprp=gsl_sysp->spr->spr;
    	struct GSL_PATTERN *ptrnp;
    	for(;i<i_max;i++){
    		if(sprp[i].visible==0)
    			continue;
    		if(sprp[i].ptrn >= gsl_sysp->max_ptrn)/* 保険 */
    			continue;
    		if(sprp[i].pal >= gsl_sysp->max_pal)/* 保険 */
    			continue;
    		ptrnp=gsl_sysp->ptrn + sprp[i].ptrn;
    		if(ptrnp->size==0){/* 保険 */
    			continue;
    		}else if(ptrnp->size==1){
    			gsl_drawptrn8g( sprp[i].x, sprp[i].y, ptrnp->adr);
    		}else if(ptrnp->size==2){
    			gsl_drawptrn16g( sprp[i].x, sprp[i].y, ptrnp->adr);
    		}else if(ptrnp->size==3){
    			gsl_drawptrn32g( sprp[i].x, sprp[i].y, ptrnp->adr);
    		}
    	}
    	return;
    }
  • 2005-03-30 (水) 17:48:18 聖人 : すいません、前回の書き込みで「下記のように…」と書いたものの、その「下記」を書き忘れていました(汗。書き加えておきます。どうもありがとうございます。いよいよスプライトまで形になりましたね。pal[*padr].cはただのパレット指定ではなく、2ドット分の色(16ビットカラーに変換済み)データなのです。こうすることにより、ニブルに分けて16ビットづつ描画するところを1バイト分読んで32ビットづつ描画することが出来、高速になるというわけです。なので描画用のパレットとしてunsigned int型の配列256個を用意して、pal[*padr].cをそいつに置き換えてください。pal[*padr].cの生成方法はdung_grp.cのsetpalを参考にお願いします。
    例)
    仮想画面サイズと実画面サイズは同じ。
    マス内の番号はBG画面の頂点からのパターン位置。
    
    +--------------------------------+
    ||   3   |   0   |   1   |   2   |
    ||   2   |   2   |   2   |   2   |
    ||       |       |       |       |
    |+-------*-------+-------+-------+
    ||       |(0,0)  |       |       |
    ||   3   | 横0   |   1   |   2   |
    ||   0   | 縦0   |   0   |   0   |
    ||       |       |       |       |
    |+-------+-------+-------+-------+
    ||       |       |       |       |
    ||   3   |   0   |   1   |   2   |
    ||   1   |   1   |   1   |   1   |
    ||       |       |       |       |
    |+-------+-------+-------+-------+
    ||       |       |       |       |
    +--------------------------------+
    
  • 2005-03-31 (木) 23:30:16 くーみん : はみ出して反対側にいくんですね、少し面倒かも…パレットの方は僕が変なのやるよりやってもらったほうがいい気がします…あと、32x32を描いているときに端が31しかない、とか言うのは考えなくていいでしょうか?とりあえず考えないでやってます
  • 2005-04-01 (金) 20:20:44 聖人 : そうです>はみ出して反対側 多分こうしていた方が作りやすいゲームもあると思うので。端が31しかない…というのはクリッピングのことですか?クリッピングは描画関数のほうで処理しているので、気にしないで大丈夫です。
  • 2005-04-03 (日) 15:13:06 くーみん : 日曜とかになるべく時間作りますが、これから少し忙しいです。端が31しかないというのは、はみ出して反対側に行くのが、基本パターンのサイズより小さかったらどうするのだろう…という意味です。「例」でも下側がそうなっているのかな…gsl_drawptrn8gを使ってその処理をするのに適当な方法が見つからないのです。基本パターンのサイズ通りであれば、サイズより大きくなれば、描画座標を引き算で(画面サイズ分引いて)小さくすればいいので簡単なんですが…drawbgでgsl_drawptrn8g(j, i, tile);を呼び出している所で、j,iの所を「実画面サイズ-8(パターンサイズ)を越えていたら(実画面サイズ-8)を引いた値を引数として与える」で問題がないと思いますが、そういうことでいいのだろうか…
  • 2005-04-03 (日) 15:23:58 くーみん : ちょっと訂正します、引数として与えるのではなく、gsl_drawptrnの方で実画面を越してたら引くようにすればいいかもしれません。そうすれば先述の問題は多少楽に解決できそうです…多分。端のサイズが中途半端でも問題ないです。でも一つ問題があって、実画面がbg画面より大きいときに、描画されない部分の形が'『'のようになってしまうかも、という事がおきそうです。それから追加ですが、gsl_faderでr,g,bをcharで定義していますが、intの方が高速かも…
  • 2005-04-05 (火) 14:09:32 聖人 : すみません、遅くなりました。了解しました>これから少し忙しいです。はみ出すサイズが基本パターンサイズより小さい場合も、基本パターンサイズ通りの時と同じような扱いでお願いします。gsl_drawptrn側で引き算の処理をすると、BG画面が実画面より大きい場合にも問題が出ませんか?これは引数で今描画しているBG画面の番号を渡すようにすれば、gsl_drawptrn側で計算して回避できますが。
  • 2005-04-05 (火) 23:17:12 くーみん : 「はみ出すサイズが基本パターンサイズより小さい場合」に対応するには、端の一列用に関数を埋め込むか、新規に書かないといけません、特に実画面右下隅も考えると面倒そうな…(うまい書き方あるんですか?)今はなるたけループの中での処理を減らしているんですが、端であるかの判定を入れる必要が出てくるわけです、高速化、は難しくなるかも。どうされるつもりでしたか?、僕が下手なだけかな…また、座標値に奇数を許してしまうと、2ドット分ずつ描画する所でも判定が必要になってしまいます、もともと高速化のために2ドットにしたわけだから、「遅くなる」というよりは、「高速化しきれない」と考えれば前向きではいいんですが。話は戻って、もしくは、drawptrnにがんばらせるか。「引数で今描画しているBG画面の番号を渡す」ように、思い切って、drawptrn自体を利用しやすく変更していくのもいいかもしれませんね。でも結局内側で分岐が(関数をいじると間接的に)増えるのは避けられないと思います。前者を重視して、実画面端の列に達するまではgsl_drawptrnを呼び出し続け、端の関数を(3つ?)書いて(改造drawptrn)、端はそれを呼び出し。あとは座標を調節してもう一度gsl_drawptrnを呼ぶのがいいかと思います。
  • 2005-04-07 (木) 00:32:24 聖人 : うーん、そこまで深く考えていませんでした…(汗。良く考えると確かにそれに対応するには、端の数だけループや分岐が増えて遅くなってしまいます。そこが描画速度のネックになるようであれば、「はみ出したら反対側にいく」という仕様自体を無くしてしまった方がいいかもしれません…。2ドット分づつ描画する事に関しての判定は最初からしないつもりでした。奇数座標を使ったら右端にはみ出したときに左端が荒くなるよ、ということで。あ、でも右下からはみ出したときはグラフィックボックス直後のメモリを破壊してしまいますね…。これはクリッピングの処理を改良して(分岐が増えないように)何とかします。
  • 2005-05-01 (日) 13:30:50 聖人 : (くーみんさん見てるかなぁ…)大変遅くなってしまいましたが、とりあえず今まで完成している部分で、動くものが出来上がりました。テストプログラムとセットにして、後ほどアップします。
  • 2005-05-03 (火) 15:43:39 聖人 : 色々あって遅くなりましたが、先程アップしました。自分のページの開発中の所に密かに追加してあります。画像アップの所にlzhファイルのアップが出来ないかと考えましたが、おかしくなると大変なのでやめておきました。
  • 2005-05-04 (水) 14:07:29 くーみん : おぉ、動くんですか。一応コンパイルエラーはでないように.objファイル作りながら作成してたんですが。tileは一回毎に++でいいんですね、そこと(gsl_sysp->ptrn + *tile)->adrで渡す所がわたしが分かってないところでした。gsl_drawbgはそのコードを元に少し高速化してみます。はみ出しに関しては、gsl_drawptrn8gの端対応関数を作って、ループを段組にするか、goto文を使ってみます。明日までにやらないとまたしばらく(長めに)時間がとれそうにないのでがんばってみます。
    	if(gsl_sysp->bg[bgnum].mode == 0){/* tile */
    		gsl_setpal(gsl_sysp->bg[bgnum].pal);
    		i_max += gsl_sysp->bg[bgnum].y;
    		j_max += gsl_sysp->bg[bgnum].x;
    		tile = gsl_sysp->bg[bgnum].tile;
    		if(gsl_sysp->ptrn->size == 1){
    			for(i = gsl_sysp->bg[bgnum].y; i < i_max; i+=8){
    				for(j = gsl_sysp->bg[bgnum].x; j < j_max; j+=8){
    					gsl_drawptrn8g(j, i, (gsl_sysp->ptrn + *tile)->adr);
    					tile++;
    				}
    			}
    		}else if(gsl_sysp->ptrn->size == 2){
    			for(i = gsl_sysp->bg[bgnum].y; i < i_max; i+=16){
    				for(j = gsl_sysp->bg[bgnum].x; j < j_max; j+=16){
    					gsl_drawptrn16g(j, i, (gsl_sysp->ptrn + *tile)->adr);
    					tile++;
    				}
    			}
    		}else if(gsl_sysp->ptrn->size == 3){
    			for(i = gsl_sysp->bg[bgnum].y; i < i_max; i+=32){
    				for(j = gsl_sysp->bg[bgnum].x; j < j_max; j+=32){
    					gsl_drawptrn32g(j, i, (gsl_sysp->ptrn + *tile)->adr);
    					tile++;
    				}
    			}
    		}
    	}else{/* if mode==1,pixel */
  • 2005-05-04 (水) 14:21:37 くーみん : とりあえずこれで動作は変わらないと思うのですが、ソースを読んでみてどうでしょう。あと、register付けているのが明らかにおかしかったですね、付けるならi,jに付けるべき…ごめんなさい。
  • 2005-05-05 (木) 18:39:33 くーみん : 次のような感じで、それぞれのブロックサイズ区切りならきちんとした動作をするプログラムが出来ると思います。ピクセルモードだと面倒かも…(やってないから分からない)
    		if(i_max<=gsl_sysp->height)
    			flag_i=0;
    		else
    			flag_i=1;;
    		if(j_max<=gsl_sysp->width)
    			flag_j=0;
    		else
    			flag_j=1;
    として、画面端をこえるか否かのflagをたてて、
    		if(gsl_sysp->ptrn->size == 1){
    			i = gsl_sysp->bg[bgnum].y;
    			if(flag_i==1){
    				i_max = gsl_sysp->height;
    			}
    		i8again:
    			for(; i < i_max; i+=8){
    				j = gsl_sysp->bg[bgnum].x;
    				if(flag_j==1){
    					j_max = gsl_sysp->width;
    				}
    			j8again:
    				for(; j < j_max; j+=8){
    					gsl_drawptrn8g(j, i, (gsl_sysp->ptrn + *tile)->adr);
    					tile++;
    				}
    				if(flag_j==1 && j_max == gsl_sysp->width){
    					j_max = gsl_sysp->v_width + gsl_sysp->bg[bgnum].x - j_max;
    					j=0;
    					goto j8again;
    				}
    			}
    			if(flag_i==1 && i_max == gsl_sysp->height){
    				i_max = gsl_sysp->v_height + gsl_sysp->bg[bgnum].y - i_max;
    				i=0;
    				goto i8again;
    			}
    比較的変更点は小さいですね、差分があればさほど読みにくくもないと思います。
    gotoでやる方が多分サイズ小さいし、速度も大差ないと思うのでそうしましたが、展開した方がいいかもしれませんね、そちらの方が高速になる可能性もありますし。flagが付くとき専用の箇所を分けると、つかない時に遅くなる事は避けられるんですがサイズが大きそう…関数ポインタと、8,16,32どれかを持つ変数を用意して、画面端越え専用として、3タイプ兼用のプログラムを書くことも出来ますね、それなら3つ分けるより重たいですが小さくなるかな。
  • 2005-05-05 (木) 18:59:48 くーみん : それで、画面端が端数となる時は別関数を用意して、書き分けることになると思うんですが、その時はjに対してi一つあたり一回の子ループを一つと、iが区切れになってきるとき用に中身が似たループを持ってくることになります。やっぱり、それをするならば、gsl_drawptrn8gの中で端越えの判定文を増やす方が、きれいで小さいですね。どれぐらい重たくなるか知りませんが…flag_j==1で判定すると、i一回あたり一回ですが、gsl_drawptrn8gの中ですと、i/8*j/8回判定になりますね。うー、わからない。
    	if(flag_j==1){
    		diff+=gsl_sysp->width;
    		j_max = gsl_sysp->width-gsl_sysp->bg[bgnum].x;
    	}else{
    		j_max = gsl_sysp->v_width;
    	}
    	if(flag_i==1){
    		i_max = gsl_sysp->height-gsl_sysp->bg[bgnum].y;
    	}else{
    		i_max = gsl_sysp->v_height;
    	}
    ipixagain:
    	for(i = 0; i < i_max; i++){
    		if(flag_j==1){
    			diff+=gsl_sysp->width;
    		}
    		unsigned short *endp = p + j_max;
    	jpixagain:
    		for(; p < endp; p++){
    			*p = *(p+diff);
    			p++;
    		}
    		if(flag_j==1){
    			flag_j++;
    			diff-=gsl_sysp->width;
    			endp+=gsl_sysp->v_width-j_max;
    			goto jpixagain;
    		}else if(flag_j==2){
    			flag_j--;
    		}
    		p += (gsl_sysp->width - gsl_sysp->v_width);
    	}
    	if(flag_i==1){
    		flag_i++;
    		i_max=gsl_sysp->v_height-i_max;
    		diff+=(int)p;
    		p = (unsigned short *) ((char *) gsl_sysp->gbox + 64);
    		diff-=(int)p;
    		goto ipixagain;
    	}
    }
  • 2005-05-05 (木) 21:02:54 くーみん : pixはこんな感じなんだろうか。.nasファイルのサイズは、-Osで、23376>22450>25715となっています。バイナリにしたらどうなるかは知りません。
  • 2005-05-06 (金) 20:31:57 聖人 : すみません、遅くなりました。たくさんありがとうございます。上のBG描画の骨組みの部分で、i_maxとj_maxをいじるのであれば、tileの画面からはみ出す部分をスキップする必要があります(自分が書いたソースでは省略していた)。後は良いと思います。画面端の処理は、gotoを使わない方が速いかもしれません。flag有り無しでコードを分ける事は、とりあえず速度を見てから考えたいと思います。端数の処理ですが、一応描画関数のクリッピングを見直して、二ドット単位の描画を維持したままそれなりに描画できるようにしました(この前アップしたものはこれで描画しています)。ただし、実画面の左右それぞれ1ラインは端数の場合描画されません。分かりやすいパターンを使ってテストしてみた限り、ほとんど目立たなかったのですが、やはりここはまじめにやるべきですかね…。
  • 2005-05-07 (土) 01:44:41 くーみん : どういうユーザーを考えて、どう使ってもらうかにもよりますからね。ループ2段にしても良かったんですが、それはそうしたかったらすぐに組めますからしませんでした。左端、1段ずれてはみ出すのなら終末判定以外いらないんですけどね、1段上げるのに苦労しますね。上下もめんどくさいですしねぇ…
  • 2005-05-13 (金) 01:22:51 聖人 : 遅くなってばっかりで申し訳ないです…。さらに申し訳ないのですが、遅くとも8月ごろまで、学校の関連(プログラミングコンテスト)に集中しなければならないので、しばらくこちらの開発に参加しづらくなります…よろしくお願いします。幅広いユーザに使ってもらうとしたら、描画関数に関しては、OSASKのグラフィックボックスみたいに丁寧モードと高速モードみたいにしたほうがいいのかもしれませんね。ループに関しては納得です。はみ出したときの処理というものは、他に良い案が思い浮かばなかったもので…。
  • 2005-05-15 (日) 00:55:18 くーみん : 了解しました。丁寧と高速を分けるのはいいかもしれません。もっというなら、必要によっていちいち呼び出す関数変えてもらうと小さくて済むという…
  • 2005-06-26 (日) 13:01:44 くーみん : 久しぶりに土日休みだったのですが、あんまり時間とれませんでした、ごめんなさい。
  • 2005-07-28 (木) 22:56:09 聖人 : (くーみんさん見てるかな…?)すみません、遅くなりました。プログラミングコンテストは一息ついたので、こちらに復活します。いきなりですが、また一部仕様を変更したいと思います。今まではパターンを定義してから、その番号でスプライトやBGに指定をしていましたが、パターン定義を廃止して直接スプライトやBGに元絵のアドレスを指定するようにしようと思います。これは、パターン数が増えると最初の登録が非常に面倒になりそうだからです。また、こちらの方が同じ絵をサイズを変えて使いたい等の場合にも対応しやすくなります。呼び出す関数を変えるとは…関数ポインタですかね?
  • 2005-07-30 (土) 12:03:19 くーみん : 直接指定、ですか。実装に関してはちょっと分かりかねます。呼び出す関数を変えるというのは、例えば丁寧、高速を、パラメータ指定ではくて、関数自体を分けてしまう、という事ですね。どちらかしか使わないような場合、小さくてすみます。
  • 2005-07-30 (土) 23:26:37 聖人 : 仕様変更は自分でやります。呼び出す関数を変える話は理解できました。平行して作るよりは、どちらかがまともになったらもう片方を作るというほうがいいような気がします。
  • 2005-08-05 (金) 01:13:58 聖人 : だいぶ遅くなってしまいましたが、8月5日中には、前回のアップからの変更を適用した動く物をアップしたいと思います。暫くお待ちくださいませ。
  • 2005-08-05 (金) 19:58:21 聖人 : はみ出して反対側に行く処理の部分で思わぬ問題(犯人は自分)が発生していまい、ちょっと手こずっています。今日中は無理かもしれません…。
  • 2005-08-06 (土) 21:38:54 聖人 : アップしました。自分が書いた部分について、全く最適化出来ていませんが(汗)とりあえず動きます。また、BG画面に表示/非表示の属性を追加しました。ついでに、テストプログラムに画面の書き換え回数/秒を表示する処理を追加しました。最適化の指標になると思います。ちなみに、うちのTOWNS(i486DX2 66MHz, 32768色表示)では15か16位です。
  • 2005-08-17 (水) 18:00:20 くーみん : ありがとうございます。8月は忙しいです。9月は結構時間がとれそうです。高速化以外にやらないといけないのは、端の処理をどうするかでしたっけ。もう少しはやいPCで30~60出れば、まぁ合格なんでしょうか。
  • 2005-08-19 (金) 19:08:42 聖人 : 了解しました>8月は忙しいです。 自分も8月中はこれから危ういです(宿題が…)。丁寧モードの端の処理はやらないといけませんね。あと、まだ未実装の処理(半透明処理など)の実装ですかね。Pentium 100MHzぐらいのAT互換機(TOWNSはVRAMにウェイトがかかっているので)で、それぐらいの速度がでれば、いい感じですね。やはり描画関数をASKAで書くべきなのかもしれません。時間があれば、自分でも挑戦してみたいと思います。
  • 2005-09-17 (土) 12:42:07 聖人 : 9月も中頃まで来てしまいましたが、9月に入った途端に文化祭関連で忙しくなってしまい、全く手付かずの状態です…。脳内で描画関数の確実に高速化可能な構想は出来たのですが、9月いっぱいまで無理そうです…。
  • 2005-10-07 (金) 17:37:23 聖人 : (くーみんさん見てるかな)遅くなってごめんなさい、ようやっと開発再開します。当面は高速化に励みたいと思います。
  • 2005-10-20 (木) 19:58:11 聖人 : ASKAを組み合わせて描画本体(gsl_drawptrn8g)を若干高速化してみました(分岐減少と486でのストール対策)。うちのTOWNSで16~18位です。他にも高速化出来そうな部分を探して高速化させたいです。あと、今更ながら、今アップロードされているブツには32*32ドットのタイルモード以外はまともに動かないことに気が付きました(滝汗。次にアップロードするときに実装しておきます。
  • 2005-10-20 (木) 21:40:41 くーみん : うぃ、なんだかんだで開発に時間が使えてません。
  • 2005-10-23 (日) 22:27:45 聖人 : 自分も脇道にそれつつ開発しているので問題ないです(汗
  • 2005-11-09 (水) 21:41:25 聖人 : 相変わらずスローペースです(汗。gsl_drawptrn8gの高速化を継続したのですが、あまり効果がありませんでした…。
  • 2005-12-08 (木) 15:31:10 聖人 : (くーみんさん見てるかな?)ようやくアップロードできそうなメドがたちました。タイルモードのはみ出し処理は完璧になったと思います。32*32以外にもちゃんと対応しました。あと以前より高速化されている気がします(汗。ソースは見づらくなりました(滝汗。多分今日中にアップロードします。
  • 2005-12-10 (土) 01:17:24 聖人 : 遅くなってしまいましたが、やっとアップ出来ました。ピクセルモードはまだ実装し直していません。動作確認の為にBG三画面(8*8,16*16,32*32)を描画するようにしたので、今までと速度の基準が変わってしまいますが、とりあえず8*8のBG殺してTOWNSで測定した所、だいたい18で安定するようになりました。三画面有効にしても13位出ます。今後はピクセルモードと半透過処理、マスク機能を実装して、それなりに動くようになったところで、実地試験ということでkaodunに実装したいと思います。
  • 2006-01-15 (日) 01:03:27 聖人 : ものっすごい調子が良かったので、半透明描画とモザイク処理をさくっと追加できました。あとはマスクとピクセルモードのみ!!
  • 2006-01-17 (火) 23:38:21 聖人 : マスクとピクセルモードを追加しました。これで完成か…と思いきや、矩形塗りつぶし関数を作り忘れてたので、それを追加したらひとまず完成にして、kaodunでテストしたいと思います。
  • 2006-01-20 (金) 17:15:51 聖人 : とりあえず動くものができたのでアップしました。またもや若干の仕様変更を行いました。実装機能的には概ね完成で良いと思います。特定画面とのマスクは、計算が大変で描画が遅くなってしまうので、実画面と同じサイズの「ビット演算画面」を作って、そいつとのビット演算でマスクを可能にしました。速度の低下は殆ど無いです。ソースを分割してライブラリファイルとテスト用の実行ファイルにしました。説明ファイルをまだ作っていないので、暫く仮公開とします。まだ高速化の余地がある場合は教えて頂けると有難いです。
  • 2006-01-28 (土) 16:23:21 聖人 : ビット演算画面のXORってあんまり使えないような気がする…。ということで、XORを捨ててNANDとNORを追加する方針で進む予定です。あと多少問題のある部分が存在するようなので、そこも直さなければ。
  • 2006-01-29 (日) 12:49:22 聖人 : やっぱり使い物になりました(汗。ということでそこらへんの変更は無しです…。
  • 2006-02-22 (水) 23:58:31 聖人 : kaodunでテストしたところ、ぼろぼろ問題が発生しているので、細々した仕様変更等をすると思います。
  • 2006-02-26 (日) 17:01:28 聖人 : kaodunでの問題が無くなりました。又、新たな仕様変更で、マスク画面のサイズを可変としました。それに伴い、実画面の横幅とマスク画面の横幅の差分を投入する変数を新たに設けました。kaodun自体は、当初の画面回りの関係の見にくさが解消され、今後のアイテム追加等がやりやすくなりましたが、その分速度がバカ落ちしました。以前はうちのTOWNSで毎秒40フレーム程度のスピードがでていたのですが、現在はたったの10フレーム程度です。現在タイルモードで実装しているので、ピクセルモードに置き換えればもっと速くなると思いますが、せっかく苦労してタイルモードを作ったのにという気がしないでも無いです。とりあえずもう少し様子を見ます。
  • 2006-03-01 (水) 22:00:45 くーみん : 見易さと速度、大変ですね。春休みにやる気が出せれば私の状況も進むと思います。
  • 2006-03-01 (水) 22:30:06 くーみん : えぇと、「マスク画面のサイズを可変としました。それに伴い、実画面の横幅とマスク画面の横幅の差分を投入する変数を新たに設けました。」でそんなに速度が落ちるんでしょうか…
  • 2006-03-02 (木) 13:32:27 くーみん : gsl_drawstr16って、32bit転送できないでしょうか。透過がめんどうなのかなぁ…gsl_setpal毎回実行する負荷ってどのぐらいかな。drawbg読んでみます。
  • 2006-03-03 (金) 22:25:41 聖人 : 結構大変そうです。突っ込み所がたくさんあると思うので宜しくお願いします。今置いてあるやつは最新版ではなくなってしまったので、後で上げ直しておきます。マスクが可変となった件ですが、描画関数を呼び出した時に、マスク画面を使う場合だけ20クロック程(486の場合)追加になります。ピクセルモードだと大した問題にはならないでしょうが、タイルモードだと結構悲惨です。kaodunで極力遅くなったのは、前のkaodunがピクセルモードもどきな描画をしていたからというのもあるのですが…。gsl_drawstr16は実画面への描画の動作がgsl_drawptrn8gと似てるので、32bit転送を含めて高速化出来そうです。おまけに半透明描画等も追加できそうです。gsl_setpalの負担はそこそこでかいと思います。描画に比べたら微々たるものでしょうが…。
  • 2006-03-04 (土) 13:40:48 くーみん : askのファイル、大体の構造はつかめたんですが、細部良く分からない処理がありました。マスク処理のせいなのかな…あとは命令のペアリングとかで少し変わるんでしょうかね。486だと…setpalはうーん、微々たるものかな。SHR(EAX, 33);のあとがマスク関係の処理になるんでしょうか。どうやって減らすんだろ…
  • 2006-03-04 (土) 16:45:35 聖人 : 遅くなりましたが、上げ直しておきました。マスク関連の処理が若干変わってますが、流れは殆ど同じです。マスク関連の前準備は/* 四つ目の引数(method)を元に、描画処理へ分岐 */の処理以降から、次の連続条件ジャンプまでです。なんだかソースが混沌と化していますが勘弁して下さい。あとPentiumのペアリングは全く考慮していません(面倒だし、Pentium以降だとそんなに速度の問題は目立たないと思うので)。が、486の部分レジスタストールは抑えるように書いた部分があります(gsl_drawptrn8gの描画ループ内)。いっそのことだからsetpalもASKAで書き直した方がいいのかもなぁ…。
  • 2006-03-04 (土) 18:07:58 聖人 : kaodunをピクセルモードにしてみましたが、TOWNSで12~13程度になっただけで大差ありませんでした…。メモリ食うのでタイルモードに戻します…。
  • 2006-03-05 (日) 21:03:55 聖人 : kaodunでどうしても必要になったので急遽機能追加しました。スプライトの座標を、スプライト画面全体の座標(ベース座標)と個々のスプライトの座標(オフセット座標)の和に変更しました。BG等は弄ってません。また上げ直したので宜しくお願いします。
  • 2006-03-06 (月) 00:47:33 くーみん : ASKAであれぐらい書いてしまうとこれ以上どう高速化したらいいやら。一番高速化の肝になるのがループの一番中の文ですけど、はたしてどれぐらい速度上げられるんでしょう…
  • 2006-03-07 (火) 18:32:44 聖人 : 結構がしがし書いたので…。ループの中は、それなりに気合を入れて書いたつもりですが、ビット演算描画の部分は若干適当な気もします。あとループに入る前の演算部分も気になります。高速化には関係ないですが、クリッピングにバグがあるようです…。結構前から潰そうとしていますが、未だ原因が特定できてません…。
  • 2006-03-08 (水) 01:02:05 くーみん : Cで書いていた時はうまくいってたんですか?それなら一度もどってゆっくり進めばいいですよね。ループの中を早くしないことにはなぁ…
  • 2006-03-11 (土) 09:43:22 聖人 : そうですね。多分Cの頃のソースは残ってたと思うのでゆっくり考えてみたいと思います。確かにgsl_drawptrn8g以外だと、ループの中を速くするべきなんですが、gsl_drawptrn8gだと、bg画面描画という大きなループの中にあるとも言えるので…。
  • 2006-03-24 (金) 19:43:22 聖人 : 上手く潰せたので、アップし直しました。犯人は描画関数呼び出し直後の、画面外除外の計算間違いでした。あと、kaodunを作っていて発見したのですが、各種描画の直接描画時に透明色が上手く扱えていなかったので、修正しました。以前は直接描画の時だけ3命令で点を打っていたのですが、バグを潰す為に、他の描画と同じく4命令での描画になってしまいました…。速度向上は全く出来ていません…。あとgsl_drawstr16も作らないといけませんね。ユーザに文字描画APIのバッファを用意させるか、それとも関数内でmallocするか…。
  • 2006-03-26 (日) 23:46:05 くーみん : ユーザー用意の方がいい気がします。mallocが関数のとマクロのと混在すると…どうなるんだろ。速度向上は難しそうですねぇ
  • 2006-03-29 (水) 20:51:04 聖人 : 了解しました。早速ユーザ用意で実装してみようかと思います。混在はどうなんでしょうね。相互にぶつかってしまいそうな気がしますが。速度向上はもう半ば諦めています…。
  • 2006-04-02 (日) 00:19:59 聖人 : とりあえずC言語で実装してみました。頭が回りきらないので自分自身でのASKA化は暫くやめておきます。妙に引数が多くなってしまいました。一応32bit形式のstringだけに対応させましたが、8bit形式base付きも対応させた方が便利なので、後にgsl_drawstr16_8gとして用意すべきと思います。
  • 2006-04-14 (金) 00:23:43 聖人 : やっと調子が乗ったので、文字描画の後半部分をASKA化しました。せっかくなので、クリッピングと演算描画、半透明描画に対応させました。14日中にアップします。
  • 2006-04-14 (金) 22:39:16 聖人 : アップしました。これで、実装すべきものは全て実装したと思います。今後はreadmeとサンプル作りに専念します。もし、まだ最適化の余地があれば教えて下さい。
  • 2006-04-23 (日) 16:49:36 聖人 : 確認なのですが、ライセンスはKL-01にして良いでしょうか? あとreadmeの最後の連絡先なのですが、くーみんさんも入れた方がいいでしょうか? 入れるとしたらどこにすれば良いですか?
  • 2006-04-30 (日) 01:30:04 くーみん : ライセンスなどはどうされても結構です。連絡先は、必要ならいれていいですが、必要でないならなくて構いません。
  • 2006-05-01 (月) 00:03:02 聖人 : 了解しました。連絡先は、自分で責任を持つ事にします。説明書は一応完成しました。後はサンプルだけだ…。
  • 2006-05-12 (金) 00:32:45 聖人 : 一応最終的な形として出来上がったのでアップしておきました。サンプル作成中に単純かつ致命的なバグを発見したので潰しておきました。一週間後にはkaodunと合わせて正式公開したいと思います。何か問題点が残っていれば教えて下さい。
  • 2006-05-12 (金) 23:32:37 くーみん : 正直もうあんまりわかんないです。頭がおっつかない。
  • 2006-05-13 (土) 20:30:00 聖人 : …わかりました……。kaodunの準備が済み次第正式公開します。
  • 2006-05-14 (日) 16:08:39 聖人 : 無事に正式公開できました。今まで協力して頂きありがとうございました。
  • 2006-05-17 (水) 15:06:57 くーみん : よかったですね。こちらこそどうも。
    お名前: コメント: []

[リロード]   [新規] [編集] [凍結] [差分] [添付]   [トップ] [一覧] [単語検索] [最終更新] [バックアップ]   [最終更新のRSS]
Last-modified: 2006/10/12 (木) 01:32:00 (4024d)