小ワザ
VRAMを直接操作してみる †
VRAMを直接弄って、HSPの画面を書き換えます。
HSPのVRAMはmref命令を使用することで取得することができます。
これをpoke命令を使って操作することで、画面の状態を変える事が出来ます。
HSPのVRAMは正確には、現在の画面の状態が格納されているわけではなく、
裏画面(オフスクリーンバッファ)の状態が格納されています。
なので、VRAMを直接弄っただけでは画面は更新されません。
VRAMへ書き込んだ状態を画面へ反映させるためには"redraw 1"を実行する必要があります。
VRAMへの書き込みは"redraw 0"を実行した後の画面描画と同じと考えてもいいと思います。
ここでVRAMの構造のお話を簡単に。
今回はフルカラーモード(24bitカラー)でのVRAMについて説明します。
パレットモードのときは少し異なってきますが、今回は説明しません。
フルカラーモードの場合は1ピクセルに対して、
R(赤)要素が1Byte(8bit)、G(緑)要素が1Byte(8bit)、B(青)要素が1Byte(8bit)の計3Byte(24bit)で構成されています。
この3Byte(24bit)のセットが先頭(左上)から右方向へ画面の面積分だけ並んでいることになります。
画面が100 x 100(ピクセル単位)の場合は、
座標(0, 0)が1Byte目〜、(1, 0)が4Byte目〜、(2, 0)が7Byte目〜...(99, 0)が298Byte目、
(0, 1)が301Byte目〜...
となります。
座標(1, 0)のR要素を操作したいなら4Byte目を、B要素を操作したいなら6Byte目を
それぞれ書き換えればいいということです。
しかし、HSP上でVRAMを扱う点で注意点があります。
実際にメモリに格納されるとき、バイト配列が反転することです。
つまり、バイト配列の末端が画面の一番右上にあたり、
バイト配列の先頭が画面の一番左下になります。
RGBの並びも、BGRになるので注意が必要です。
例えば幅4px高さ4pxのウィンドウのVRAMは次の図のようになります。
数字が何バイト目か、背景色が何色の情報を示すかを表しています。
以上は幅が4の整数倍のときの話。
正確にはVRAMの横幅アドレスは。
vwidth = ( ( ginfo_winx * 3 ) + 3 ) & 0xfffffffc
で計算します。
詳しくはSDKマニアル参照↓
x = X座標;
y = Y座標;
width = ((sx*3)+3)&~3;
vram_adr = pBit + ( ( sy - 1 - y ) * width ) + ( x * 3 )
+
| | サンプルコード
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
|
| #ifndef __vram_draw__
#module _vram_draw_
#define __vram_draw__
#deffunc vram_pset int px, int py
mref vram, 66
index = (ginfo(12) * ginfo(13)) - ( (py + 1) * ginfo(12) - px)
poke vram, index * 3, ginfo(18) poke vram, index * 3 + 1, ginfo(17) poke vram, index * 3 + 2, ginfo(16)
return
#global
#endif
color 0,0,255
repeat 100
y = cnt
repeat 100
x = cnt
vram_pset x + 100, y + 100
loop
loop
redraw 1
wait 200
color 255,0,255
repeat 100
y = cnt
repeat 100
x = cnt
pset x + 100, y + 100
loop
loop
redraw 1
|
|
執筆中。
+
| | サンプルコード
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
|
| #module
#deffunc PickRGB str p1
switch (p1)
case "R" :case "r" :x = 0 :swbreak
case "G" :case "g" :x = 1 :swbreak
default :x = 2 :swbreak
swend
mref BMSCR, 67 mref VRAM, 66
repeat (BMSCR(1)*BMSCR(2)*3/4)
VRAM(cnt) &= RGB( cnt\3, x )
loop
return
#deffunc Initialize
dim RGB, 3, 3
RGB(0,0) = 0x00FF0000, 0x0000FF00, 0xFF0000FF RGB(0,1) = 0x0000FF00, 0xFF0000FF, 0x00FF0000 RGB(0,2) = 0xFF0000FF, 0x00FF0000, 0x0000FF00 return
#global
Initialize
buffer 1
picload dirinfo(1)+"/sample/demo/sky_bg.jpg"
x1 = GINFO_WINX
y1 = GINFO_WINY
buffer 2
picload dirinfo(1)+"/sample/demo/jp6girl.bmp"
x2 = GINFO_WINX
y2 = GINFO_WINY
screen 0, 640, 480
gmode 0 :gcopy 1, 0, 0, x1, y1
gmode 2 :gcopy 2, 0, 0, x2, y2
redraw 0
PickRGB "R" redraw 1
|
|
- シンプルで高速な色反転をしたくて作りました。お気に入りです。--りさ
+
| | サンプルコード:変数経由
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
|
|
sdim szFileName, 1024 szFileName = "test.bmp"
sdim cBMPHeader, 64 bload szFileName, cBMPHeader
bfSize = lpeek(cBMPHeader, 2) bfOffBits = lpeek(cBMPHeader, 10)
biWidth = lpeek(cBMPHeader, 18) biHeight = lpeek(cBMPHeader, 22)
sdim cBMPData, bfSize - bfOffBits bload szFileName, cBMPData, (bfSize - bfOffBits), bfOffBits
screen 0, biWidth, biHeight mref mVRAM, 66
memcpy mVRAM, cBMPData, bfSize - bfOffBits
redraw 1
stop
|
|
- 24bitのBMPファイルの画像データ部分とフルカラーモード(24bitカラー)の時のVRAMのデータ構造がそっくりなので、試してみました。
このサンプルは、24bitのWindows BMP、RLE非圧縮専用です--つくね?
- このサンプルでは、一度、変数(cBMPData)にBMPファイルの画像データを読み込んでいますが、読込先を変数(mVRAM)にすれば
直接VRAMにロードできそうな予感がします(試す場合は自己責任で。)
- あ、memfileを使うなら、bloadの前に入れれば良かったかも。
memfileは画像の枚数が多くてバッファーを使いまわす時に使えそうな気がします。
+
| | サンプルコード:VRAMに直接読み込む版
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
|
|
sdim szFileName, 1024 szFileName = "test.bmp"
sdim cBMPHeader, 64 bload szFileName, cBMPHeader
bfSize = lpeek(cBMPHeader, 2) bfOffBits = lpeek(cBMPHeader, 10)
biWidth = lpeek(cBMPHeader, 18) biHeight = lpeek(cBMPHeader, 22)
screen 0, biWidth, biHeight mref mVRAM, 66
bload szFileName, mVRAM, (bfSize - bfOffBits), bfOffBits
redraw 1
stop
|
|
- 前回のコードを改造して、VRAMに直接読み込む版も作ってみました。--つくね?
- bufferも同じ原理でいけるかも?
と思いましたが、前回の変数経由で使った変数(cBMPData)がバッファーと同じ役割に使えそうです。
- 3Byteのセットが面積分よりも多く並んでいるものもあります。 -- dummy?