4: 2004-01-24 (土) 13:34:51 |
現: 2024-01-08 (月) 12:59:00 ゲスト |
| [[introx]] | | [[introx]] |
| | | |
| + | |
| "mt_xor1.c"の解説 | | "mt_xor1.c"の解説 |
| 2004/01/22 | | 2004/01/22 |
- | ベイサイド(bayside_yokohama@yahoo.co.jp) | + | ベイサイド |
| + | |
| このドキュメントは、"mt_xor1.c"の説明だけをするものです。最初に読むべきドキュ | | このドキュメントは、"mt_xor1.c"の説明だけをするものです。最初に読むべきドキュ |
| メントではありません。最初に読むべきドキュメントは"document.txt"です。"mt_xor0 | | メントではありません。最初に読むべきドキュメントは"document.txt"です。"mt_xor0 |
| .c"との違いは32ビットグラフィックボックスを使うことです。 | | .c"との違いは32ビットグラフィックボックスを使うことです。 |
- | | + | |
| + | |
| 1.アルゴリズム | | 1.アルゴリズム |
| + | |
| 今まで説明してきた描画方法は点を打つとか線を引くというものでした。しかし実際 | | 今まで説明してきた描画方法は点を打つとか線を引くというものでした。しかし実際 |
| のプログラムでは、もっと込み入ったことがやりたいというのはよくあることです。そ | | のプログラムでは、もっと込み入ったことがやりたいというのはよくあることです。そ |
| の場合、あたかもビデオメモリにアクセスするように自由に読み書きできれば、なにか | | の場合、あたかもビデオメモリにアクセスするように自由に読み書きできれば、なにか |
| と便利でしょう。・・・ここでは、そういうアクセス方法を説明します。 | | と便利でしょう。・・・ここでは、そういうアクセス方法を説明します。 |
| + | |
| このアクセス方法は2つの手順で構成されます。まず、指定されたバッファ内に自由に | | このアクセス方法は2つの手順で構成されます。まず、指定されたバッファ内に自由に |
| 読み書きします。このバッファはグラフィックボックスに対応しており、4バイトが1ド | | 読み書きします。このバッファはグラフィックボックスに対応しており、4バイトが1ド |
| できません。いじったら必ずflushしてください(リードアクセスしかしていないときは | | できません。いじったら必ずflushしてください(リードアクセスしかしていないときは |
| flushしなくてもよい)。 | | flushしなくてもよい)。 |
| + | |
| グラフィックボックスのバッファ構造は、(int *) gbox + 16から後ろのxsize * ysi | | グラフィックボックスのバッファ構造は、(int *) gbox + 16から後ろのxsize * ysi |
| ze * 4がそっくりそのままバッファになっています。単純明快です。詳しいことはソー | | ze * 4がそっくりそのままバッファになっています。単純明快です。詳しいことはソー |
| スをご覧ください。 | | スをご覧ください。 |
| + | |
| このプログラムはその方法でたくさんの点を描画して、ちょっとした「山」を描きま | | このプログラムはその方法でたくさんの点を描画して、ちょっとした「山」を描きま |
| す。 | | す。 |
- | | + | |
| + | |
| 2.ライブラリ関数の説明 | | 2.ライブラリ関数の説明 |
| + | |
| 引数の型については、guigui00.hを参照してください。 | | 引数の型については、guigui00.hを参照してください。 |
| + | |
| lib_flushgraphbox(opt, win, x, y, sx, sy, skip, p) : | | lib_flushgraphbox(opt, win, x, y, sx, sy, skip, p) : |
| + | |
| グラフィックボックスをflushします。optは0x8024にしてください。winはグラフィッ | | グラフィックボックスをflushします。optは0x8024にしてください。winはグラフィッ |
| クボックスが所属するウィンドウです。残りのパラメーターが少々ややこしいです。ま | | クボックスが所属するウィンドウです。残りのパラメーターが少々ややこしいです。ま |
| ずグラフィックボックス全体をflushするなら、 | | ずグラフィックボックス全体をflushするなら、 |
| + | |
| x, y : グラフィックボックスオープン時に指定したx_pos, y_posの値 | | x, y : グラフィックボックスオープン時に指定したx_pos, y_posの値 |
| sx, sy : グラフィックボックスオープン時に指定したx_size, y_sizeの値 | | sx, sy : グラフィックボックスオープン時に指定したx_size, y_sizeの値 |
| skip : 必ず0 | | skip : 必ず0 |
| p : (int *) gbox + 16 | | p : (int *) gbox + 16 |
| + | |
| という風に指定します。しかしいじった範囲がグラフィックボックスのごく一部である | | という風に指定します。しかしいじった範囲がグラフィックボックスのごく一部である |
| という場合もよくあるでしょう。そんなときこのような全範囲flushをすると処理時間に | | という場合もよくあるでしょう。そんなときこのような全範囲flushをすると処理時間に |
| おいてかなりの無駄になります。そんな時は部分flushを使います。 | | おいてかなりの無駄になります。そんな時は部分flushを使います。 |
| + | |
| x, y : 部分flushしたい範囲の左上の座標(window内の座標系で指定・・・gboxの | | x, y : 部分flushしたい範囲の左上の座標(window内の座標系で指定・・・gboxの |
| 座標ではない) | | 座標ではない) |
| skip : (グラフィックボックスオープン時に指定したx_size - この時のsx) * 4 | | skip : (グラフィックボックスオープン時に指定したx_size - この時のsx) * 4 |
| p : x, yで指定した座標に相当するドットを指し示すintポインタ | | p : x, yで指定した座標に相当するドットを指し示すintポインタ |
| + | |
| これをよくご覧になれば分かるように、結局は全範囲flushも部分flushも同じルールで | | これをよくご覧になれば分かるように、結局は全範囲flushも部分flushも同じルールで |
| す。 | | す。 |
| + | |
| もしたとえば画面内でキャラクターが走っているとすれば、まずはバッファにアクセ | | もしたとえば画面内でキャラクターが走っているとすれば、まずはバッファにアクセ |
| スして、元いた場所を背景に戻して移動先にキャラクターを書き込むでしょう。そして | | スして、元いた場所を背景に戻して移動先にキャラクターを書き込むでしょう。そして |
| 。できるだけ狭い範囲に分解してやりましょう。・・・この時以下の2つの方法のどちら | | 。できるだけ狭い範囲に分解してやりましょう。・・・この時以下の2つの方法のどちら |
| がいいかと迷われるかもしれません。 | | がいいかと迷われるかもしれません。 |
| + | |
| 1.移動元書き換え → 移動元flush → 移動先書き換え → 移動先flush | | 1.移動元書き換え → 移動元flush → 移動先書き換え → 移動先flush |
| 2.移動元書き換え → 移動先書き換え → 移動元flush → 移動先flush | | 2.移動元書き換え → 移動先書き換え → 移動元flush → 移動先flush |
| + | |
| もちろんどちらの手順でも問題なく実行できますが、どちらかといえば2.の方がおす | | もちろんどちらの手順でも問題なく実行できますが、どちらかといえば2.の方がおす |
| すめです。というのは、結局画面に反映されるのはflushの時なので、2.の方法の方が | | すめです。というのは、結局画面に反映されるのはflushの時なので、2.の方法の方が |
| ターが介在しているのなら、まずはバッファ内の書き換えを集中させ、その後にflushを | | ターが介在しているのなら、まずはバッファ内の書き換えを集中させ、その後にflushを |
| 集中的にやる方が良いでしょう。 | | 集中的にやる方が良いでしょう。 |
| + | |
| 3.改造への指針 | | 3.改造への指針 |
| + | |
| このバッファへのアクセスとflushを使えば、かなり自由にグラフィック処理ができる | | このバッファへのアクセスとflushを使えば、かなり自由にグラフィック処理ができる |
| はずです。しかしflushの際にはVRAMへアクセスすることになり、これは結構重たい処理 | | はずです。しかしflushの際にはVRAMへアクセスすることになり、これは結構重たい処理 |
| // stack:4k malloc:6k | | // stack:4k malloc:6k |
| // copyright(C) 2004 ベイサイド | | // copyright(C) 2004 ベイサイド |
| + | |
| #include <guigui00.h> | | #include <guigui00.h> |
| + | |
| #define AUTO_MALLOC 0 | | #define AUTO_MALLOC 0 |
| + | |
| /* ちょっとしたマクロ */ | | /* ちょっとしたマクロ */ |
| #define pixel(x, y) *(p + (y) * 100 + (x)) | | #define pixel(x, y) *(p + (y) * 100 + (x)) |
| + | |
| /* 基本的なアルゴリズム */ | | /* 基本的なアルゴリズム */ |
| /* 1.グラフィックボックスをオープンする */ | | /* 1.グラフィックボックスをオープンする */ |
| そこを好きなようにいじる(リードしてもライトしてもいい) */ | | そこを好きなようにいじる(リードしてもライトしてもいい) */ |
| /* 3.いじり終ったら、バッファをflushしなければいけない。この時点で画面に反映される */ | | /* 3.いじり終ったら、バッファをflushしなければいけない。この時点で画面に反映される */ |
| + | |
| void OsaskMain() | | void OsaskMain() |
| { | | { |
| int i, j; | | int i, j; |
| int *p; | | int *p; |
| + | |
| lib_init(AUTO_MALLOC); | | lib_init(AUTO_MALLOC); |
| window = lib_openwindow(AUTO_MALLOC, 0x0200, 136, 48); | | window = lib_openwindow(AUTO_MALLOC, 0x0200, 136, 48); |
| wintitle = lib_opentextbox(0x1000, AUTO_MALLOC, 0, 7, 1, 0, 0, window, 0x00c0, 0); | | wintitle = lib_opentextbox(0x1000, AUTO_MALLOC, 0, 7, 1, 0, 0, window, 0x00c0, 0); |
| lib_putstring_ASCII(0x0000, 0, 0, wintitle, 0, 0, "Mt.Xor0"); | | lib_putstring_ASCII(0x0000, 0, 0, wintitle, 0, 0, "Mt.Xor0"); |
| + | |
| /* グラフィックボックスをウィンドウに用意する */ | | /* グラフィックボックスをウィンドウに用意する */ |
| graphicbox = lib_opengraphbox(1, AUTO_MALLOC, 4, 8, 100, 48, 18, 0, window); | | graphicbox = lib_opengraphbox(1, AUTO_MALLOC, 4, 8, 100, 48, 18, 0, window); |
| y_pos : グラフィックボックスの位置(ドット単位) | | y_pos : グラフィックボックスの位置(ドット単位) |
| */ | | */ |
| + | |
| p = (int *) graphicbox + 16; | | p = (int *) graphicbox + 16; |
| + | |
| /* 頂点に一つ点を打つ */ | | /* 頂点に一つ点を打つ */ |
| pixel(49, 0) = 0; /* 黒い点 */ | | pixel(49, 0) = 0; /* 黒い点 */ |
| + | |
| /* ちょっとした演算 */ | | /* ちょっとした演算 */ |
| for (j = 0; j < 47; j++) { | | for (j = 0; j < 47; j++) { |
| pixel(i, j + 1) = ((pixel(i - 1, j) == 0) ^ (pixel(i + 1, j) == 0)) ? 0 : 0xC6C6C6; | | pixel(i, j + 1) = ((pixel(i - 1, j) == 0) ^ (pixel(i + 1, j) == 0)) ? 0 : 0xC6C6C6; |
| } | | } |
| + | |
| j = 0; | | j = 0; |
| for (;;) { | | for (;;) { |
| + | |
| /* バッファの内容を確実に画面に反映させる */ | | /* バッファの内容を確実に画面に反映させる */ |
| lib_flushgraphbox(0x8024, window, 18, 0, 100, 48, 0, p); | | lib_flushgraphbox(0x8024, window, 18, 0, 100, 48, 0, p); |
| skip : 0(固定) | | skip : 0(固定) |
| p : (int *) graphbox + 16 | | p : (int *) graphbox + 16 |
| + | |
| なお、上記の例はグラフィックボックス全体をflushしている | | なお、上記の例はグラフィックボックス全体をflushしている |
| */ | | */ |
| + | |
| lib_waitsignaltime(0x0007, 0, 0, 0x80000000, 0, 0); /* 500msec.-wait */ | | lib_waitsignaltime(0x0007, 0, 0, 0x80000000, 0, 0); /* 500msec.-wait */ |
| + | |
| /* 色変更 */ | | /* 色変更 */ |
| j = (j + 1) & 0x868686; | | j = (j + 1) & 0x868686; |
| p[i] = j; | | p[i] = j; |
| } | | } |
| + | |
| } | | } |
| } | | } |
| -説明がt_xor0と重複しすぎていて、読み手が飛ばし読みをする恐れがあったので、違いのみをピックアップして書き直しました。 | | -説明がt_xor0と重複しすぎていて、読み手が飛ばし読みをする恐れがあったので、違いのみをピックアップして書き直しました。 |
| | | |
| + | |
| "mt_xor1.c"の解説 | | "mt_xor1.c"の解説 |
| 2004/01/24 | | 2004/01/24 |
| 川合秀実(kawai@osask.jp) | | 川合秀実(kawai@osask.jp) |
| + | |
| このドキュメントは、"mt_xor1.c"の説明だけをするものです。最初に読むべきドキュ | | このドキュメントは、"mt_xor1.c"の説明だけをするものです。最初に読むべきドキュ |
| メントではありません。最初に読むべきドキュメントは"document.txt"です。 | | メントではありません。最初に読むべきドキュメントは"document.txt"です。 |
- | | + | |
| + | |
| 1.アルゴリズム | | 1.アルゴリズム |
| + | |
| このmt_xor1は、mt_xor0の改造版に相当します。違いは8ビットグラフィックボックス | | このmt_xor1は、mt_xor0の改造版に相当します。違いは8ビットグラフィックボックス |
| ではなく32ビットグラフィックボックスを使うことです。mt_xor0を理解してから読んで | | ではなく32ビットグラフィックボックスを使うことです。mt_xor0を理解してから読んで |
| ください。 | | ください。 |
| + | |
| グラフィックボックスのバッファ構造は、LIB_GBOX_BUF32(gbox)から後ろのxsize * | | グラフィックボックスのバッファ構造は、LIB_GBOX_BUF32(gbox)から後ろのxsize * |
| ysize * 4がそっくりそのままバッファになっています。詳しいことはソースをご覧く | | ysize * 4がそっくりそのままバッファになっています。詳しいことはソースをご覧く |
| となっています。8bitグラフィックボックスと同様に、自由に読み書きして、必要に応 | | となっています。8bitグラフィックボックスと同様に、自由に読み書きして、必要に応 |
| じてflushしてください。 | | じてflushしてください。 |
- | | + | |
| + | |
| 2.ライブラリ関数の説明 | | 2.ライブラリ関数の説明 |
| + | |
| 引数の型については、guigui00.hを参照してください。 | | 引数の型については、guigui00.hを参照してください。 |
| + | |
| lib_flushgraphbox(opt, win, x, y, sx, sy, skip, p) : | | lib_flushgraphbox(opt, win, x, y, sx, sy, skip, p) : |
| + | |
| グラフィックボックスをflushします。optは0x8004か0x8024にしてください。winは | | グラフィックボックスをflushします。optは0x8004か0x8024にしてください。winは |
| グラフィックボックスが所属するウィンドウです。残りのパラメーターが少々ややこし | | グラフィックボックスが所属するウィンドウです。残りのパラメーターが少々ややこし |
| いです。まずグラフィックボックス全体をflushするなら、 | | いです。まずグラフィックボックス全体をflushするなら、 |
| + | |
| x, y : グラフィックボックスオープン時に指定したx_pos, y_posの値 | | x, y : グラフィックボックスオープン時に指定したx_pos, y_posの値 |
| sx, sy : グラフィックボックスオープン時に指定したx_size, y_sizeの値 | | sx, sy : グラフィックボックスオープン時に指定したx_size, y_sizeの値 |
| skip : 必ず0 | | skip : 必ず0 |
| p : LIB_GBOX_BUF32(gox) | | p : LIB_GBOX_BUF32(gox) |
| + | |
| という風に指定します。 | | という風に指定します。 |
| + | |
| 32ビットグラフィックボックスで部分フラッシュをすることもできます。その場合は | | 32ビットグラフィックボックスで部分フラッシュをすることもできます。その場合は |
| 次のように引数を指定します。 | | 次のように引数を指定します。 |
| + | |
| x, y : 部分flushしたい範囲の左上の座標(window内の座標系で指定・・・gboxの | | x, y : 部分flushしたい範囲の左上の座標(window内の座標系で指定・・・gboxの |
| 座標ではない) | | 座標ではない) |
| skip : (グラフィックボックスオープン時に指定したx_size - この時のsx) * 4 | | skip : (グラフィックボックスオープン時に指定したx_size - この時のsx) * 4 |
| p : x, yで指定した座標に相当するドットを指し示すポインタ | | p : x, yで指定した座標に相当するドットを指し示すポインタ |
| + | |
| optの違いについてですが、通常は0x8004を使います。色表現力が犠牲になってもいい | | optの違いについてですが、通常は0x8004を使います。色表現力が犠牲になってもいい |
| から、速度を速くしてほしいという場合に限って(もしくはすべての画面モードで細い | | から、速度を速くしてほしいという場合に限って(もしくはすべての画面モードで細い |
| 線がタイリングで点線に化けたりするのが不都合な場合)、0x8024を指定します。 | | 線がタイリングで点線に化けたりするのが不都合な場合)、0x8024を指定します。 |
- | | + | |
| + | |
| 3.改造への指針 | | 3.改造への指針 |
| + | |
| これをつかえば8ビットグラフィックボックスでは得られなかった高い表現力が得られ | | これをつかえば8ビットグラフィックボックスでは得られなかった高い表現力が得られ |
| るでしょう。今のところ(完成度が低いせいで)32ビットグラフィックボックス内でラ | | るでしょう。今のところ(完成度が低いせいで)32ビットグラフィックボックス内でラ |
| // stack:4k malloc:20k | | // stack:4k malloc:20k |
| // copyright(C) 2004 Hidemi KAWAI | | // copyright(C) 2004 Hidemi KAWAI |
| + | |
| #include <guigui00.h> | | #include <guigui00.h> |
| + | |
| #define AUTO_MALLOC 0 | | #define AUTO_MALLOC 0 |
| + | |
| /* ちょっとしたマクロ */ | | /* ちょっとしたマクロ */ |
| #define pixel(x, y) *(p + (y) * 100 + (x)) | | #define pixel(x, y) *(p + (y) * 100 + (x)) |
| #define LIB_GBOX_BUF32(gbox) ((unsigned int *) LIB_GBOX_BUF(gbox)) | | #define LIB_GBOX_BUF32(gbox) ((unsigned int *) LIB_GBOX_BUF(gbox)) |
| #endif | | #endif |
| + | |
| void OsaskMain() | | void OsaskMain() |
| { | | { |
| 0x000000, 0x840000, 0x008400, 0x848400, 0x000084, 0x840084, 0x008484, 0x848484 | | 0x000000, 0x840000, 0x008400, 0x848400, 0x000084, 0x840084, 0x008484, 0x848484 |
| }; | | }; |
| + | |
| lib_init(AUTO_MALLOC); | | lib_init(AUTO_MALLOC); |
| window = lib_openwindow(AUTO_MALLOC, 0x0200, 136, 48); | | window = lib_openwindow(AUTO_MALLOC, 0x0200, 136, 48); |
| wintitle = lib_opentextbox(0x1000, AUTO_MALLOC, 0, 7, 1, 0, 0, window, 0x00c0, 0); | | wintitle = lib_opentextbox(0x1000, AUTO_MALLOC, 0, 7, 1, 0, 0, window, 0x00c0, 0); |
| lib_putstring_ASCII(0x0000, 0, 0, wintitle, 0, 0, "Mt.Xor1"); | | lib_putstring_ASCII(0x0000, 0, 0, wintitle, 0, 0, "Mt.Xor1"); |
| + | |
| /* グラフィックボックスをウィンドウに用意する */ | | /* グラフィックボックスをウィンドウに用意する */ |
| graphicbox = lib_opengraphbox(1, AUTO_MALLOC, 4, 0xc6c6c6, 100, 48, 18, 0, window); | | graphicbox = lib_opengraphbox(1, AUTO_MALLOC, 4, 0xc6c6c6, 100, 48, 18, 0, window); |
| y_pos : グラフィックボックスの位置(ドット単位) | | y_pos : グラフィックボックスの位置(ドット単位) |
| */ | | */ |
| + | |
| p = LIB_GBOX_BUF32(graphicbox); | | p = LIB_GBOX_BUF32(graphicbox); |
| + | |
| /* 頂点に一つ点を打つ */ | | /* 頂点に一つ点を打つ */ |
| pixel(49, 0) = 0x000000; /* 黒い点 */ | | pixel(49, 0) = 0x000000; /* 黒い点 */ |
| + | |
| /* ちょっとした演算 */ | | /* ちょっとした演算 */ |
| for (j = 0; j < 47; j++) { | | for (j = 0; j < 47; j++) { |
| pixel(i, j + 1) = pixel(i - 1, j) ^ pixel(i + 1, j) ^ 0xc6c6c6; | | pixel(i, j + 1) = pixel(i - 1, j) ^ pixel(i + 1, j) ^ 0xc6c6c6; |
| } | | } |
| + | |
| j = 0; | | j = 0; |
| for (;;) { | | for (;;) { |
| なお、上記の例はグラフィックボックス全体をflushしている | | なお、上記の例はグラフィックボックス全体をflushしている |
| */ | | */ |
| + | |
| lib_waitsignaltime(0x0007, 0, 0, 0x80000000, 0, 0); /* 500msec.-wait */ | | lib_waitsignaltime(0x0007, 0, 0, 0x80000000, 0, 0); /* 500msec.-wait */ |
| + | |
| /* 色変更 */ | | /* 色変更 */ |
| j = (j + 1) & 7; | | j = (j + 1) & 7; |