カラーパレットをかえてみよう
MSXにはカラー・パレットというものがある。
今のPCなら余りあるメモリでビットマップでも余裕で処理できるが、MSXはVRAMが最大128キロバイトしかないので、表現できる色は512色あるけど、そのうち16色しか使えないという制限がある。その16色をカラー・パレットというのだ。
デフォルトでは下表のように設定されているぞ。
パレット番号 | 色 | パレット番号 | 色 |
---|---|---|---|
0 | 周辺色 | 8 | 赤 |
1 | 黒 | 9 | 明るい赤 |
2 | 緑 | 10 | 黄 |
3 | 明るい緑 | 11 | 明るい黄 |
4 | 暗い青 | 12 | 暗い緑 |
5 | 明るい青 | 13 | 紫 |
6 | 暗い赤 | 14 | 灰 |
7 | 水色 | 15 | 白 |
まずはCOLORでかえてみよう
当然、このパレットの色を変えることができる。
BASICではCOLORステートメントを使う。やってみよう。
パレットの色を変える
1000 SCREEN 1 : PRINT "PUSH ANY KEY" : GOSUB 2000
1010 COLOR=(4,7,0,0) : GOSUB 2000
1020 COLOR=(4,0,7,0) : GOSUB 2000
1030 COLOR=(4,0,0,7) : GOSUB 2000
1040 COLOR=(4,5,5,5) : GOSUB 2000
1050 COLOR=NEW
1060 END
2000 I$=INKEY$ : IF I$="" THEN 2000
2010 RETURN
実行結果の絵は割愛するが、何かキーを押すたびに背景の色が、赤→緑→青→灰→青に変わるぞ。
デフォルトでは背景色のパレットが4なので、パレット番号4の色を変えている。
カッコのなかの1番左の数値がパレット番号、そして右へ順番に赤色(Red)の輝度、緑色(Green)の輝度、青色(Blue)の輝度となっている。
それぞれの輝度は3ビットであらわされるので、数値では0~7(000B~111B)ということになる。赤8×緑8×青8=512通り(色)というわけだな。
最後のNEWは、パレットが初期化されるぞ。
VRAM操作でかえてみよう
カラー・パレットは、VRAM上ではパレット・テーブルという領域に保存されている。
この領域はスクリーンモード毎に違うのでデータパックなどで確認してくれたまえ。
今回のサンプルはスクリーン1を使うので、データパックによると2020Hから32バイトということらしい。
先頭アドレスからパレット0が定義され、1パレットにつき、2バイト使用している。
その情報は次の図の通り。
それぞれ3ビットなので、1バイトに収まらないので2バイトなんだな。
それじゃ、やってみよう。
VRAMでパレットの色を変える
1000 SCREEN 1
1010 COLOR=(4,1,2,3) : GOSUB 1500
1020 GOSUB 2000
1100 SCREEN 1
1110 VPOKE &H2020+(4*2),&H13
1120 VPOKE &H2020+(4*2)+1,&H2
1130 GOSUB 1500 : GOSUB 2000
1140 END
1500 PRINT HEX$(VPEEK(&H2020+(4*2)))
1510 PRINT HEX$(VPEEK(&H2020+(4*2)+1))
1520 RETURN
2000 I$=INKEY$ : IF I$="" THEN 2000
2010 RETURN
実行結果
結論からいうと失敗だ。
初めはCOLORステートメントでパレットを変更した後、対象のパレット・テーブルを表示している。
赤=1、緑=2、青=3と設定しているので、その内容が正しく表示されており、背景色も変化している。
次は、VRAMを変更した後、対象のパレットテーブルを表示している。
対象のVRAMアドレスに同じ値を設定したのだが、背景色は変化していない。
しかし、VRAMの値は変更した値になっているのだ。
要するに、VRAMを変更しただけではパレットは変化しないということだな。
何か別の方法があるはずだ。
ということで調べましたよ。
VDP(n)でかえてみよう
データパックによると、VDPにはパレットレジスタなるものがあるらしい。
BASICではVDP(n)というシステム関数でアクセスできる。VDP(n)の詳しいことは次の投稿を参照してくれたまい。
そして、パレットレジスタR#16に変更したいパレット番号をセットした後、ポート#2に赤と青、もう一度ポート#2に緑の輝度をセットすればいいらしい。
VDPにはポートが4つあり、ポート#2はMAIN ROMの07H番地の値に2を足したアドレスのI/Oポートらしい。
らしいばっかりだな!
MAIN ROMの07H番地の値はPEEK関数によると98Hだったので、+2すると9AHだな。
で、BASICでポートに出力するには、OUTステートメントを使えばよい。やってみよう。
VDP(n)でパレットを変える
1000 SCREEN 1
1010 COLOR=(4,1,2,3) : GOSUB 1500
1020 GOSUB 2000
1100 SCREEN 1
1110 VDP(17)=4
1120 OUT &H9A,&H13
1130 OUT &H9A,&H02
1140 GOSUB 1500 : GOSUB 2000
1150 END
1500 PRINT HEX$(VPEEK(&H2020+(4*2)))
1510 PRINT HEX$(VPEEK(&H2020+(4*2)+1))
1520 RETURN
2000 I$=INKEY$ : IF I$="" THEN 2000
2010 RETURN
実行結果
前回のサンプルのVPOKEだったところを、VDP(n)とOUTにしたのがこれだ。
ちゃんと背景色が変わっているぞ。成功だ。
でも、パレット・テーブルは変わらないんかい!
今はこれが限界だな。
じゃまた。
おまけ
512色をお試しできるプログラムをつくってみたよ。
「R」「G」「B」キーを押すとそれぞれ赤緑青の輝度が上がり、シフト+「R」「G」「B」キーを押すと輝度が下がるよ。
それに合わせて、真ん中のスプライトの色が変化するぞ。
512色お試し
1000 SCREEN 1,1 : WIDTH 32 : DEFINT A-Z
1010 A$="" : FOR I=0 TO 7
1020 A$=A$+CHR$(&HFF)
1030 NEXT : SPRITE$(0)=A$
1040 PUT SPRITE 0,(16*8-8,11*8-8),1
1050 R=0 : G=0 : B=0 : GOSUB 3000
2000 I$=INKEY$
2010 IF I$="r" AND R<7 THEN R=R+1
2020 IF I$="R" AND R>0 THEN R=R-1
2030 IF I$="g" AND G<7 THEN G=G+1
2040 IF I$="G" AND G>0 THEN G=G-1
2050 IF I$="b" AND B<7 THEN B=B+1
2060 IF I$="B" AND B>0 THEN B=B-1
2070 GOSUB 3000
2080 GOTO 2000
3000 COLOR=(1,R,G,B)
3010 LOCATE 11,15 : PRINT "RED = ";R
3020 LOCATE 11,16 : PRINT "GREEN = ";G
3030 LOCATE 11,17 : PRINT "BLUE = ";B
3040 RETURN