GBAの画面上への点や背景の表示

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
トナカイ

GBAの画面上への点や背景の表示

#1

投稿記事 by トナカイ » 14年前

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増やさないといけないような気がしてしまうのですが…
すみませんが、どなたか解説お願いします。

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 15年前
住所: 東海地方
連絡を取る:

Re: GBAの画面上への点や背景の表示

#2

投稿記事 by softya(ソフト屋) » 14年前

GBAで開発したことがないのでハードウェアを理解してませんがptr の型が分からないと答えようがありません。 ※ptrの型が2バイトのデータ型なんじゃないかと推測されます。
あと描画モードも関係するかも知れません。
出来ればGBAのハード仕様のサイトや参考にしているサイトも教えて下さい。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

beatle
記事: 1281
登録日時: 14年前
住所: 埼玉
連絡を取る:

Re: GBAの画面上への点や背景の表示

#3

投稿記事 by beatle » 14年前

質問自体はGBAとは切り離すことができますね。単なるポインタ演算についての質問ですね。
どうしてポインタに1を加算するだけで2番地増えるのか。
ポインタ演算に書いてあることが役立つでしょう。

トナカイ

Re: GBAの画面上への点や背景の表示

#4

投稿記事 by トナカイ » 14年前

学校の先生が作ったテキストをもとに作っているので
疑問解消の為に少し調べる以外にはサイトなどをあまり見ていないのですが、
先生の作ったテキストによれば
GBAのVRAMの領域は0x06000000から0x06017FFFまでの96kバイトで、
バス幅は16ビット、液晶ディスプレイは240*160ドットで構成され、左上の0ドット目が0x06000000番地からの2バイトに相当するそうです。
あと、質問内のptrはunsigned short型のポインタです。
説明不足ですみません。

beatleさんの紹介して下さったサイトと上記の情報を合わせてみて、背景描画のときは
ptr = ptr + 1;
の記述で番地を2増やしていることになっていて、
ある座標に点を打つときはポインタ演算でないので
2ずつ増やさなければならないのかなという考えに行き着きました。
この考え方で合っているでしょうか?

beatle
記事: 1281
登録日時: 14年前
住所: 埼玉
連絡を取る:

Re: GBAの画面上への点や背景の表示

#5

投稿記事 by beatle » 14年前

トナカイ さんが書きました: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の画面上への点や背景の表示

#6

投稿記事 by トナカイ » 14年前

「ある座標に点を打つときはポインタ演算でない」というのは
下のようなコードを想定しての発言だったのですが、
beatleさんの解説をきくとそれも間違いのようですね。

コード:

 
typedef volatile unsigned short hword;
#define VRAM 0x06000000

//中略

void draw_point(hword x,hword y,hword color){
	hword *p;
	p =(hword*) (VRAM + x*2 + y*480);
	*p = color;
}
 
ということは、この場合もp=(hword*) (VRAM + x + y*240)としなければならないのでしょうか?

beatle
記事: 1281
登録日時: 14年前
住所: 埼玉
連絡を取る:

Re: GBAの画面上への点や背景の表示

#7

投稿記事 by beatle » 14年前

トナカイ さんが書きました: ということは、この場合もp=(hword*) (VRAM + x + y*240)としなければならないのでしょうか?
それは違います。VRAMは整数型であってポインタ型ではないですから、
VRAM + foo
(fooは整数型とする)と書くと、整数型同士の演算となります。
ポインタ演算ではありませんので、この場合は足す数を2倍する必要があります。

もし
p= (hword*)VRAM + x + y*240
なんて書いたら、VRAMのキャストが加算より優先度が高いため、ポインタ演算になります。
そのため、足す数は2倍してはいけません。

beatle
記事: 1281
登録日時: 14年前
住所: 埼玉
連絡を取る:

Re: GBAの画面上への点や背景の表示

#8

投稿記事 by beatle » 14年前

まとめると
  • ポインタ演算とはポインタ型と整数型の演算
  • ポインタ演算では、整数型の数値をポイント先の型のサイズ倍する
    例:ポインタの型がFoo*だったら、整数型の数値をsizeof(Foo)倍してから演算する
ということになります。

トナカイ

Re: GBAの画面上への点や背景の表示

#9

投稿記事 by トナカイ » 14年前

わざわざまとめまでありがとうございます。では、
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関数の中身は合っているという理解でよろしいでしょうか?

beatle
記事: 1281
登録日時: 14年前
住所: 埼玉
連絡を取る:

Re: GBAの画面上への点や背景の表示

#10

投稿記事 by beatle » 14年前

draw_point関数は、shortが2バイトの環境でなら意図した動きになるはずです。
しかし自前で2倍するのではなく、ポインタ演算で自動で2倍するようにした方が、移植性は高くなると思います。

トナカイ

Re: GBAの画面上への点や背景の表示

#11

投稿記事 by トナカイ » 14年前

なるほど、確かにポインタ演算をした方が汎用性が高いですね。
ポインタ演算の存在意義が少しわかった気がします。
そしてとりあえず、現時点で抱いていた疑問は解消されました‼
何回も回答してくださって、本当にありがとうございました。

ISLe
記事: 2650
登録日時: 15年前
連絡を取る:

Re: GBAの画面上への点や背景の表示

#12

投稿記事 by ISLe » 14年前

GBAのCPUはARMだとか。
2倍するのを忘れると奇数アドレスにアクセスした途端に落ちると思います。

ポインタ演算を使うようにすれば謎のバグからも解放されることでしょう。

閉鎖

“C言語何でも質問掲示板” へ戻る