GBAの画面上への点や背景の表示
-
トナカイ
GBAの画面上への点や背景の表示
C言語を使ってGBAの画面上の(x,y)に点を打つとき、
点を打ちたい場所の番地は
0x06000000 + x*2 + y*480
となるのは理解出来たのですが、
なぜ背景の色を変えるときに
for(i=0;i<240*160;i++){
*ptr = color;
ptr = ptr + 1;
}
となるのかがわかりません。
x座標が1増えるとn番地からn+2番地になるのなら
for文の最後でptrの値を2増やさないといけないような気がしてしまうのですが…
すみませんが、どなたか解説お願いします。
点を打ちたい場所の番地は
0x06000000 + x*2 + y*480
となるのは理解出来たのですが、
なぜ背景の色を変えるときに
for(i=0;i<240*160;i++){
*ptr = color;
ptr = ptr + 1;
}
となるのかがわかりません。
x座標が1増えるとn番地からn+2番地になるのなら
for文の最後でptrの値を2増やさないといけないような気がしてしまうのですが…
すみませんが、どなたか解説お願いします。
- softya(ソフト屋)
- 副管理人
- 記事: 11677
- 登録日時: 15年前
- 住所: 東海地方
- 連絡を取る:
Re: GBAの画面上への点や背景の表示
GBAで開発したことがないのでハードウェアを理解してませんがptr の型が分からないと答えようがありません。 ※ptrの型が2バイトのデータ型なんじゃないかと推測されます。
あと描画モードも関係するかも知れません。
出来ればGBAのハード仕様のサイトや参考にしているサイトも教えて下さい。
あと描画モードも関係するかも知れません。
出来ればGBAのハード仕様のサイトや参考にしているサイトも教えて下さい。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。
-
トナカイ
Re: GBAの画面上への点や背景の表示
学校の先生が作ったテキストをもとに作っているので
疑問解消の為に少し調べる以外にはサイトなどをあまり見ていないのですが、
先生の作ったテキストによれば
GBAのVRAMの領域は0x06000000から0x06017FFFまでの96kバイトで、
バス幅は16ビット、液晶ディスプレイは240*160ドットで構成され、左上の0ドット目が0x06000000番地からの2バイトに相当するそうです。
あと、質問内のptrはunsigned short型のポインタです。
説明不足ですみません。
beatleさんの紹介して下さったサイトと上記の情報を合わせてみて、背景描画のときは
ptr = ptr + 1;
の記述で番地を2増やしていることになっていて、
ある座標に点を打つときはポインタ演算でないので
2ずつ増やさなければならないのかなという考えに行き着きました。
この考え方で合っているでしょうか?
疑問解消の為に少し調べる以外にはサイトなどをあまり見ていないのですが、
先生の作ったテキストによれば
GBAのVRAMの領域は0x06000000から0x06017FFFまでの96kバイトで、
バス幅は16ビット、液晶ディスプレイは240*160ドットで構成され、左上の0ドット目が0x06000000番地からの2バイトに相当するそうです。
あと、質問内のptrはunsigned short型のポインタです。
説明不足ですみません。
beatleさんの紹介して下さったサイトと上記の情報を合わせてみて、背景描画のときは
ptr = ptr + 1;
の記述で番地を2増やしていることになっていて、
ある座標に点を打つときはポインタ演算でないので
2ずつ増やさなければならないのかなという考えに行き着きました。
この考え方で合っているでしょうか?
Re: GBAの画面上への点や背景の表示
「ある座標に点を打つときはポインタ演算でない」とは具体的にどのようなソースコードを想定しているのでしょうか?トナカイ さんが書きました:beatleさんの紹介して下さったサイトと上記の情報を合わせてみて、背景描画のときは
ptr = ptr + 1;
の記述で番地を2増やしていることになっていて、
ある座標に点を打つときはポインタ演算でないので
2ずつ増やさなければならないのかなという考えに行き着きました。
この考え方で合っているでしょうか?
例えば、指定した点に指定した色を描く関数を作るとします。
void DrawPoint(int x, int y, uint16_t color)
{
uint16_t* vram = reinterpret_cast<uint16_t*>(0x06000000);
vram[y * 240 + x] = color; // 0x06000000 + 2 * (y * 240 + x) に color 色の点を打つ。
}
vram[y * 240 + x]
という記述は
*(vram + y * 240 + x)
と同じ意味ですので、ポインタ演算をしていると言えるでしょう。
-
トナカイ
Re: GBAの画面上への点や背景の表示
「ある座標に点を打つときはポインタ演算でない」というのは
下のようなコードを想定しての発言だったのですが、
beatleさんの解説をきくとそれも間違いのようですね。 ということは、この場合もp=(hword*) (VRAM + x + y*240)としなければならないのでしょうか?
下のようなコードを想定しての発言だったのですが、
beatleさんの解説をきくとそれも間違いのようですね。 ということは、この場合もp=(hword*) (VRAM + x + y*240)としなければならないのでしょうか?
Re: GBAの画面上への点や背景の表示
それは違います。VRAMは整数型であってポインタ型ではないですから、トナカイ さんが書きました: ということは、この場合もp=(hword*) (VRAM + x + y*240)としなければならないのでしょうか?
VRAM + foo
(fooは整数型とする)と書くと、整数型同士の演算となります。
ポインタ演算ではありませんので、この場合は足す数を2倍する必要があります。
もし
p= (hword*)VRAM + x + y*240
なんて書いたら、VRAMのキャストが加算より優先度が高いため、ポインタ演算になります。
そのため、足す数は2倍してはいけません。
Re: GBAの画面上への点や背景の表示
まとめると
- ポインタ演算とはポインタ型と整数型の演算
- ポインタ演算では、整数型の数値をポイント先の型のサイズ倍する
例:ポインタの型がFoo*だったら、整数型の数値をsizeof(Foo)倍してから演算する
-
トナカイ
Re: GBAの画面上への点や背景の表示
わざわざまとめまでありがとうございます。では、
p= (hword*)VRAM + x * 2 + y * 480
と書いた場合、pが指す番地は(VRAM + x * 2 * 2 + y * 480 * 2)番地で、
p= (hword*)(VRAM + x * 2+ y * 480)
と書いた場合、pが指す番地は(VRAM + x * 2 + y * 480)番地なので、
先ほどのdraw_point関数の中身は合っているという理解でよろしいでしょうか?
p= (hword*)VRAM + x * 2 + y * 480
と書いた場合、pが指す番地は(VRAM + x * 2 * 2 + y * 480 * 2)番地で、
p= (hword*)(VRAM + x * 2+ y * 480)
と書いた場合、pが指す番地は(VRAM + x * 2 + y * 480)番地なので、
先ほどのdraw_point関数の中身は合っているという理解でよろしいでしょうか?
Re: GBAの画面上への点や背景の表示
draw_point関数は、shortが2バイトの環境でなら意図した動きになるはずです。
しかし自前で2倍するのではなく、ポインタ演算で自動で2倍するようにした方が、移植性は高くなると思います。
しかし自前で2倍するのではなく、ポインタ演算で自動で2倍するようにした方が、移植性は高くなると思います。
-
トナカイ
Re: GBAの画面上への点や背景の表示
なるほど、確かにポインタ演算をした方が汎用性が高いですね。
ポインタ演算の存在意義が少しわかった気がします。
そしてとりあえず、現時点で抱いていた疑問は解消されました‼
何回も回答してくださって、本当にありがとうございました。
ポインタ演算の存在意義が少しわかった気がします。
そしてとりあえず、現時点で抱いていた疑問は解消されました‼
何回も回答してくださって、本当にありがとうございました。
Re: GBAの画面上への点や背景の表示
GBAのCPUはARMだとか。
2倍するのを忘れると奇数アドレスにアクセスした途端に落ちると思います。
ポインタ演算を使うようにすれば謎のバグからも解放されることでしょう。
2倍するのを忘れると奇数アドレスにアクセスした途端に落ちると思います。
ポインタ演算を使うようにすれば謎のバグからも解放されることでしょう。