ファミコン用の半透明カートリッジ(448円)

またファミコン用カートリッジのガワ(シェル)を買ってみました。

AliExpressのEurbo - Professinal Supplierというショップの「Game card Cartridge Replacement Plastic Shell Game Card case」です。色は半透明の「transparent black」です。本当は完全に透明のが欲しいのですが、みあたりませんでした。

価格は1個368円。今回は3個買って、送料240円が加わって、最終的に1,345円となりました。1個あたり約448円という計算になります。

  

f:id:nicotakuya:20201122193201j:plain

ファミコン用カートリッジのガワ

 見た目はこんな感じです。ちゃんとガワが分離した状態で届きました。以前、合体した状態で届いて、殻割りに失敗して爪が折れてしまった事があったので助かりました。

 

f:id:nicotakuya:20201214151225j:plain

ニッパーで切断

残念ながら、というか当然ですが、自分が作った 基板とポッチの位置が合いません。なのでポッチ部分をニッパで切断して、ホットボンドで付け直します。ファミコンのカートリッジは規格がバラバラなのが困り物です。

f:id:nicotakuya:20201214151430j:plain

組み合わせるとこうなります

完成しました。

樹脂はおそらくABSですね。アクリルやスチロール樹脂と違って頑丈です。厚みがあるので、かなり強い力を加えないと閉じてくれませんでした。

 

f:id:nicotakuya:20201215150716j:plain

内部にLed 搭載

動作中の様子です。透明のメリットは中身を確認できることです。自作基板だとアピールするlこも役立ちます。

 

PCエンジンのプログラミング(その7)実機で動かす

注文したプリント基板が届きましたので、PCエンジン用のメモリカード(HuCard)を自作してみました。

 


DIY PCE Card(PC Engine homebrew)

f:id:nicotakuya:20201208111428j:plain

ひとまず動くレベルに到達

結果、うまく動きましたので、資料を以下のページに公開しました。

sites.google.com

 

自作のデモプログラムも公開しています。「PCエンジンのプログラミングその1~6」で紹介したプログラムをつなぎ合わせたプログラムです。

f:id:nicotakuya:20201208111636p:plain

デモプログラム

f:id:nicotakuya:20201210101429j:plain

実機で動作している様子

こんな感じです。BGがスクロールしながら、64個のスプライトが動き、音が鳴ります。シューティングゲーム向きのPCエンジンというだけあって、快適に動いています。

 

f:id:nicotakuya:20201208110831j:plain

基板の請求書

プリント基板は「P板.com」で20枚作りましたが、価格は税込みで25,828円でした。

PCエンジンmini」が2台買えるくらいのお値段です。 もっと安く済ませる方法があると思いますが、あまり安く作れてしまうと違法コピーに利用される可能性があるので、これでいいかなと思っています。

 

f:id:nicotakuya:20201208111716j:plain

コネクタが売ってません

今回、一番無駄に苦労したのが、メモリカードのコネクタまわりです。PCエンジンは比較的マイナーなせいか、コネクタが全然売っていません。GAMEBANKとかいうメーカーから1980円の吸い出し用のコネクタ基板が売っているのですが、、、高すぎです(個人の感想)

しかたないので、2.54mmのピンソケット/ピンヘッダで2列にして接続してしまったのですが、コネクタが邪魔になるので、できれば1.27mmピッチのエッジ部分で接続したいです。サンハヤトの1.27mmのシール基板を使うとか、Micro:bitのコネクタを切断して使ってもいいかもしれません。

 

(追記2020/12/9)

「売ってない」と言った矢先に売ってました。

f:id:nicotakuya:20201209070732j:plain

売ってました

1580円、、、うーむ。

 

PCエンジンのプログラミング(その6)サウンド出力

nicotakuya.hatenablog.com
前回の続きです。HuCを使ったPCエンジンのプログラミングについて紹介します。

ここまで順調に進んできましたが、今回の課題は超苦手分野、、、サウンド出力です。
困ったことにHuCにはサウンド出力の機能が入ってません。
ドキュメントを見ても
「PSG player is started, and will be available soon(近いうちに公開)
とあります。これが書かれたのが2005年ですが、更新は2020年現在まで止まっています。

f:id:nicotakuya:20201204003855p:plain
PSG関連の関数が存在する?

ライブラリが対応していないと、どうしようもありません。ただ、不思議なことにライブラリのソースを見ると、それらしい関数の名前(PSG_~)は存在しています。もしかして、ソースを少し修正するだけで使えるようになるかもしれません。

f:id:nicotakuya:20201204003933p:plain
GitHubサウンドライブラリを発見

あと、いろいろ検索すると、HuC関連のサンプルプログラムがヒットしました。
https://github.com/uli/huc

これを見ると「st.c」「st.h」というサウンドのライブラリが存在しています。ローカルのhucフォルダ内にはこのファイルはありません。知らないところでアップデートしてるのでしょうか。
しかし、このライブラリは自前のhucではコンパイルできませんでした。なぜできないのか、原因がわかりません。
ここで、完全に手詰まりになってしまったのですが、hucのdocフォルダを漁ってみると、「PSG.txt」というテキストファイルを発見しました。

f:id:nicotakuya:20201204004038p:plain
サウンドレジスタの解説

今まで「資料がない」と愚痴ってましたが、、、反省です。
この「PSG.txt」を読むと、PCエンジンサウンド系のレジスタについて書かれています。
番地やビットの配置がわかりましたので、次のプログラムを作ってみました。

/*PSG test*/
/* based by "huc-3.21-win\doc\pce\psg.txt" */

#include "huc.h"

const char waveform[]={
 18,22,24,26,28,28,30,30,30,30,28,28,26,24,22,18,
 12, 8, 6, 4, 2, 2, 0, 0, 0, 0, 2, 2, 4, 6, 8,12
};

#define FREQ12BIT 254
/*12bit freq = (3580000/32)/Frequency */

char *psgch;    /*Channel*/
char *psgmvol;  /*Master Volume*/
char *psgfreql; /*Frequency*/
char *psgfreqh; /*Frequency*/
char *psgctrl;  /*control*/
char *psglrvol; /*L/R Volume*/
char *psgdata;  /*Waveform*/

main()
{
	int i;

	psgch   = 0x800;
	psgmvol = 0x801;
	psgfreql= 0x802;
	psgfreqh= 0x803;
	psgctrl = 0x804;
	psglrvol= 0x805;
	psgdata = 0x806;

	disp_on();
	cls();

	vsync();

	*psgch = 0;		/*Channel*/

	*psgctrl = (1<<6); 	/*reset*/
	*psgctrl = (0<<6); 	/*waveform transfer*/
	for(i=0;i<32;i++){
		*psgdata = waveform[i];	/*Waveform*/
	}

	*psgfreql = FREQ12BIT & 0xff;	/*Frequency L*/
	*psgfreqh = FREQ12BIT >> 8;	/*Frequency H*/

	*psglrvol = 0xff;	/*L/R Volume*/
	*psgmvol = 0xee;	/*Master Volume*/
	*psgctrl = (1<<7)+ 0x1f; /*Channel on*/

	put_string("PSG TEST 440Hz",3,3);

	while(1){
		vsync();
	}
}

こんな感じです。世界一シンプルなサウンドドライバです。
使用しているチャンネルは0番。周波数は440Hzです。

f:id:nicotakuya:20201204101605p:plain
波形データ

波形のデータはPSG.txtからコピペしました。波形は32バイトで表現します。振幅の範囲はPSG.txtに0~32と書かれていますが、正しくは0~31でしょうか。

f:id:nicotakuya:20201204004138p:plain
実行結果。440Hzの音を鳴らし続けます

ビルドして、ROMイメージをPCエンジンエミュレータで実行すると、「ポー」という感じの音が鳴り続けます。
これはサウンド系のレジスタを直接叩くという、過激なプログラムです。まだ安全性が確認できていません。
もっと良い方法があるかもしれないので、引き続き検討してみたいです。

(追記2020/12/05)
ノート番号を変えたり、左右の音量を変えられるようにしてみました。

f:id:nicotakuya:20201205070145p:plain
表計算ソフトでレジスタ値を計算

表計算ソフトのpower関数を使ってノート番号から周波数を計算して、
そこからさらにレジスタの値を計算してみました。
周波数設定のレジスタの値は(3580000/32)/周波数で計算できます。

/*PSG test2*/
/* based by "huc-3.21-win\doc\pce\psg.txt" */

#include "huc.h"

const char waveform[]={
	18,22,24,26,28,28,30,30,30,30,28,28,26,24,22,18,
	12, 8, 6, 4, 2, 2, 0, 0, 0, 0, 2, 2, 4, 6, 8,12
};


const int freqtbl[]={
	428,	/* note60	262Hz */
	404,	/* note61	277Hz */
	381,	/* note62	294Hz */
	360,	/* note63	311Hz */
	339,	/* note64	330Hz */
	320,	/* note65	349Hz */
	302,	/* note66	370Hz */
	285,	/* note67	392Hz */
	269,	/* note68	415Hz */
	254,	/* note69	440Hz */
	240,	/* note70	466Hz */
	227	/* note71	494Hz */
};

char *psgch;    /*Channel*/
char *psgmvol;  /*Master Volume*/
char *psgfreql; /*Frequency*/
char *psgfreqh; /*Frequency*/
char *psgctrl;  /*control*/
char *psglrvol; /*L/R Volume*/
char *psgdata;  /*Waveform*/

char wave_cnt;

/**/
wave_init()
{
	int i;

	psgch   = 0x800;
	psgmvol = 0x801;
	psgfreql= 0x802;
	psgfreqh= 0x803;
	psgctrl = 0x804;
	psglrvol= 0x805;
	psgdata = 0x806;

	vsync();

	*psgch = 0;		/*Channel*/

	*psgctrl = (1<<6); 	/*reset*/
	*psgctrl = (0<<6); 	/*waveform transfer*/
	for(i=0;i<32;i++){
		*psgdata = waveform[i];	/*Waveform*/
	}
	*psgmvol = 0xee;	/*Master Volume*/
	wave_cnt = 0;
}

/**/
wave_play(note, volume, length)
char note, volume, length;
{
	int reg;

	reg = freqtbl[note % 12];

	note -= 60;
	while(note < 0){
		note += 12;
		reg <<= 1;
	}
	while(note >= 12){
		note -= 12;
		reg >>= 1;
	}

	*psgfreql = reg & 0xff;	/*Frequency L*/
	*psgfreqh = reg >> 8;	/*Frequency H*/

	*psglrvol = volume;	/*L/R Volume*/
	*psgctrl = (1<<7) + 0x1f; /*Channel on(volume=31)*/

	wave_cnt = length;
}

/**/
main()
{
	char test,note,volume;

	wave_init();
	disp_on();
	cls();

	put_string("PSG TEST",2,2);
	put_string("NOTE NUMBER:  0x",4,4);
	put_string(" L/R VOLUME:  0x",4,6);

	test = 0;
	while(1){
		vsync();
		if(wave_cnt > 0){
			wave_cnt--;
			if(wave_cnt==0){
/*				*psglrvol = 0;*/
				*psgctrl = (0<<7) + 0x0;
			}
		}
		if(wave_cnt==0){
			note = 60+(test % 12);
			if(test < 12){
				volume = 0xff;
			}else if(test < 24){
				volume = 0x0f;
			}else{
				volume = 0xf0;
			}
			put_hex(note  , 2, 20,4);
			put_hex(volume, 2, 20,6);
			wave_play(note, volume, 100);
			test++;
			if(test >= 12*3) test=0;
		}
	}
}
f:id:nicotakuya:20201205070016p:plain
ノート番号と左右の音量を変更

実行するとノート番号60~71番までを順番に鳴らします。音の出力は左右、右のみ、左のみの順番で切り替わります。
音が止まる時にプツンという短い音が出てしまいます。どこかプログラムが間違っていると思います。

PCエンジンのプログラミング(その5)マップ表示

nicotakuya.hatenablog.com
前回に続いて、「HuC」を使ったPCエンジンのプログラミング方法について紹介します。
前回はBGの表示に成功しましたが、今度はBGをスクロールさせます。単にスクロールするだけではなく、表示画面より大きなマップ内を動いているように見せたいと思います。これを「マップ機能」と呼ぶことにします。

f:id:nicotakuya:20201202101044p:plain
画面スクロールのサンプル「SCROLL」

マップ機能についてはサンプルの「SCROLL」が参考になります。
このプログラムではBGが横方向にスクロールします。表示サイズは32×24セルですが、96×24セルのマップを移動しているように表現しています。
画面下にある32×4セルのBGはスクロールさせません。この固定した画面を「パネル」と呼んでいます。

f:id:nicotakuya:20201202101525p:plain
load_map関数

マップ機能ではBGは2×2セル(16×16ピクセル)で1つのパーツとして扱います。HuCではこれを「タイル」と呼んでいるのですが、個人的にはパターンのことをタイルと呼びたいので、混同を避けるために「マップチップ」と呼ぶことにします。マップ全体のサイズは96×24セルですが、マップを格納する配列の要素は48×12です。
ソースのSCROLL.cを見て、わかったことは、、、
・サンプルのマップチップは10種類。0~9番の番号が割り振られている。
・scroll関数でBGをスクロールさせる。scroll関数の第1引数がウインドウ番号。スクロールする画面をウインドウ0番、パネルをウインドウ1番に割り振ることで、1枚のBGを2枚に見せている。
・#inctileマクロでマップチップの画像のポインタを設定する。
・set_map_data関数を使ってマップのサイズとデータを設定する。
・set_tile_data関数でマップチップを設定する。この段階ではパターンはVRAMに転送されていない。
・load_tile関数を呼ぶと、パターンがVRAMに転送される。
・load_map関数を使ってBGを描画する。最初の一回だけは、表示画面全部を描く。
・16ピクセルぶんスクロールするたびに、load_map関数を使って、BGを部分的に描き足す。
、、、こんな感じです。マップ機能のために新しい関数がたくさん出てきます。

f:id:nicotakuya:20201202104622p:plain
0x600番地とは一体?

あと、ソースを見て気になったのが「0x600」という記述です。資料がなくて、これの意味がよくわかりませんでした。
VRAMのアドレスですよね。なぜ0x3FFより大きいのか?

f:id:nicotakuya:20201202104706p:plain
0x601番地に変更した場合

ためしに「0x601」に変更したら、BATの設定が1セルぶんズレました。
なので、ウインドウ1のBATの格納開始位置は0x600番地なのかなと思います。間違っていたらすみません。
続いて、横スクロールを行うプログラムを新しく作ります。
マップチップの素材を描きます。

f:id:nicotakuya:20201202105208p:plain
マップの素材

BMPPNGで保存します。色は16色までに限定します。

f:id:nicotakuya:20201202104527p:plain
#inctileの格納方法

初登場の#inctileマクロですが、前回の#incchrマクロとは違って、8x8ピクセルずつジグザグにデータ化します。

f:id:nicotakuya:20201202104755p:plain
マップチップ用の変換モードを追加

この仕様に対応するため、SPEDITにマップチップ用の変換機能を新しく追加しました。
https://sites.google.com/site/yugenkaisyanico/sprite-editor
変換すると、バイナリファイル「map_pattern.bin」「map_palette.bin」が生成されます。パターン用に10種類×64=640ワードのVRAMを消費します。パレットは0番にします。
パネルの素材を描きます。使える色は16色までです。

f:id:nicotakuya:20201202105233p:plain
パネルの素材

BMPPNGで保存します。

f:id:nicotakuya:20201202104848p:plain
BATをカスタマイズできるように

BGデータに変換します。
パネルのタイル番号は512番以降に割り振ることにします。256番~295番まではマップチップに使っているためです。パレットは2番です。
そこで、SPEDITにカスタマイズ機能を追加してみました。
変換すると、バイナリファイル「bg_pattern.bin」「bg_palette.bin」「bg_bat.bin」が生成されます。この3つのファイルの役割は前回と同じです。
パターン用に32×4×16=2048ワードもVRAMを使ってしまいます。

f:id:nicotakuya:20201202104937p:plain
マップデータのバイナリ化

あと、マップデータがソースにあると邪魔なので、バイナリ化してみました。これはちょっと手抜きです。本格的にゲームを作りたいという場合には、マップエディタが必要になると思います。
以上の素材がそろったので、あとはプログラムです。

/* scroll test by takuya matsubara*/
/* original program:scrolling demo(by David Michel)*/
#include "huc.h"

#define MAP_VRAM     0x1000
#define PANEL_VRAM   0x2000
#define BAT2_VRAM    0x0600

#define MAP_PAL      0
#define PANEL_PAL    2

#incbin(panel_pattern, "bg_pattern.bin")
#incbin(panel_pal, "bg_palette.bin")
#incbin(panel_bat, "bg_bat.bin")
#incbin(map_pattern, "map_pattern.bin")
#incbin(map_pal, "map_palette.bin")
#incbin(demo_map,"mapdata.bin")

#define MAP_WIDTH  48
#define MAP_HEIGHT 12
#define NB_TILE    12

const char map_pal_ref[NB_TILE] = {
	MAP_PAL<<4, MAP_PAL<<4, MAP_PAL<<4, MAP_PAL<<4,
	MAP_PAL<<4, MAP_PAL<<4, MAP_PAL<<4, MAP_PAL<<4,
	MAP_PAL<<4, MAP_PAL<<4, MAP_PAL<<4, MAP_PAL<<4
};

int sx,map_x;
int score;

main()
{
	disp_off();
	cls();

	set_map_data(demo_map, MAP_WIDTH, MAP_HEIGHT);
	set_tile_data(map_pattern, NB_TILE, map_pal_ref);
	load_tile(MAP_VRAM);
	load_palette(MAP_PAL, map_pal, 1);
	load_map(0, 0, 0, 0, 34/2, 24/2);
	set_font_pal(PANEL_PAL);

	load_vram(PANEL_VRAM, panel_pattern, 32*4*16);
	load_bat(BAT2_VRAM, panel_bat, 32, 4);
	load_palette(PANEL_PAL, panel_pal, 1);
	put_string("score: ", 1, 25);

	scroll(0, 0,    0,    0, (24*8)-1, 0xC0);
	scroll(1, 0, 24*8, 24*8, (28*8)-1, 0x80);

	disp_on();

	sx = 0;
	map_x = 0;
	score = 0;

	while(1){
		sx++;
		if((sx & 0xF) == 0) {
			map_x ++;
			if (map_x  >= MAP_WIDTH){
				map_x -= MAP_WIDTH;
			}
			load_map(
			  (sx + 256) >> 4,0,  /* sx,sy */
			   map_x + (32/2), 0, /* map x,y */
			   (2/2), (24/2));    /* w,h */

			score += 1;
		}
		put_number(score, 5, 8, 25);

		scroll(0, sx, 0, 0, ((24*8)-1), 0xC0);
		vsync();
	}
}

サンプルのSCROLLから機能を削っただけのプログラムです。BGをスクロールさせたら、16ピクセルごとにload_mapを呼んでいます。
これをビルドしてROMイメージを作ります。

f:id:nicotakuya:20201202105011p:plain
実行結果。マップがスクロールする

PCエンジンエミュレータで実行すると、こうなります。無事にスクロールさせることができました。
ひたすら、右方向にスクロールします。マップチップが48個ぶん進んだら、最初に戻ります。

PCエンジンのプログラミング(その4)BGの表示

nicotakuya.hatenablog.com
前回の続きです。今回は「BG」を表示したいと思います。
PCエンジンはとにかく資料が見当たらないです。頼りになるのはサンプルの「PONG」だけです。

f:id:nicotakuya:20201129010530p:plain
サンプルのPONG

PONGではBGを表示するために「#incchr」「#incpal」「#incbat」という3つのマクロを使っています。
このマクロの機能を調べるために次のようなプログラムを作ってみました。

/*BG dump by takuya matsubara*/
#include "huc.h"

#define BACKGROUND_FILE "special.pcx"
#incchr(bg_pattern,BACKGROUND_FILE,32,28);
#incpal(bg_palette,BACKGROUND_FILE);
#incbat(bg_bat,BACKGROUND_FILE,0x1000,32,28);

main()
{
	int i;
	char x,y;

	disp_on();
	cls();

	put_string("Pattern",1,1);
	for(i=0;i<66;i++){
		x=(i % 6)*5+1;
		y=(i/6)+2;
		put_hex(bg_pattern[i], 4, x,y);
	}

	put_string("Palette",1,14);
	for(i=0;i<24;i++){
		x=(i % 6)*5+1;
		y=(i/6)+15;
		put_hex(bg_palette[i], 4, x,y);
	}

	put_string("BAT(Background Attribute Table)",1,20);
	for(i=0;i<36;i++){
		x=(i % 6)*5+1;
		y=(i/6)+21;
		put_hex(bg_bat[i], 4, x,y);
	}

	while(1){
		vsync();
	}
}

以上のプログラムをPCエンジンエミュレータで実行すると、こうなります。

f:id:nicotakuya:20201130141434p:plain
実行結果

PONGの背景の画像をBGデータ化してダンプ表示します。画像はPCXファイル(special.pcx)です。
本来はもっと大量にデータがあるのですが、画面の都合で表示数を制限しています。
これを見て、わかったことは次の通り。
「#incchr」はパターンを生成するマクロ。1ピクセルのデータ量は4bit(16色)。タイル1枚あたり8×8ピクセル=データ量は16ワード。
「#incpal」はパレットを生成するマクロ。スプライト用でも使用。1色16bitのうち実データ9bit(緑3+赤3+青3bit)。全部で16色×16パレット=256ワード。
「#incbat」はBATを生成するマクロ。BAT(Background Attribute Table)というのは、タイル番号などを格納したバッファです。ファミコンでいうところのネームテーブルです。1セルを表現するために1ワード消費します。bit15~12がカラーパレット番号で、bit11~0がタイル番号です。タイル番号は0x100番から始まっています。おそらく、0x100番未満はフォントに使っているのではないでしょうか。これに関係して、VRAMの0x1000番地からパターンデータが格納されます。
サンプルのBGの描画サイズが32×28セル。なので、BAT全体のデータ量は896ワードです。BATはVRAMの0x0000~0x03FF番地(0x037F?)に格納されるようです。
要するにパターン+パレット+BATの3要素がBGには必要ということです。以上を参考にして、自作ツール(spedit)に機能を追加しました。
https://sites.google.com/site/yugenkaisyanico/sprite-editor

f:id:nicotakuya:20201130144111p:plain
BGのテストパターンを自動生成

メニューで「16色test(PC Engine BG)」ボタンを押すと、テストパターンのBGデータを自動生成します。
「bg_pattern.bin」「bg_palette.bin」「bg_bat.bin」という3つのバイナリファイルを作ります。スプライトと違って、BGはパターンデータの格納方法が特殊すぎるのですが、詳しくはspeditのソースを見てください。
続いて、BGを表示するプログラムを改良しました。

/*BG dump2 by takuya matsubara*/
#include "huc.h"

#incbin(bg_pattern,"bg_pattern.bin");
#incbin(bg_palette,"bg_palette.bin");
#incbin(bg_bat    ,"bg_bat.bin");

main()
{
	int i;
	char x,y;
	int work;

	disp_on();
	cls();

	put_string("Pattern",1,1);
	for(i=0;i<66;i++){
		x=(i % 6)*5+1;
		y=(i / 6)+2;
		work = bg_pattern[i*2]+0x100*bg_pattern[i*2+1];
		put_hex(work, 4, x,y);
	}

	put_string("Palette",1,14);
	for(i=0;i<24;i++){
		x=(i % 6)*5+1;
		y=(i / 6)+15;
		work = bg_palette[i*2]+0x100*bg_palette[i*2+1];
		put_hex(work, 4, x,y);
	}

	put_string("BAT(Background Attribute Table)",1,20);
	for(i=0;i<36;i++){
		x=(i % 6)*5+1;
		y=(i / 6)+21;
		work = bg_bat[i*2]+0x100*bg_bat[i*2+1];
		put_hex(work, 4, x,y);
	}

	while(joy(0)==0){
		vsync();
	}

	load_background(bg_pattern, bg_palette, bg_bat, 32, 28);
	for(i=0;i<16;i++){
		put_string("<Palette=",16,i);
		put_hex(i, 1, 16+9,i);
	}
	while(1){
		vsync();
	}
}

ここでは「#incbin」マクロでBGデータのバイナリファイルを組み込みます。「#incchr」「#incpal」「#incbat」マクロが不要になります。
エミュレータで実行すると、こうなります。

f:id:nicotakuya:20201130141523p:plain
実行結果

ここでゲームパッドのボタンを押すと、、、

f:id:nicotakuya:20201130141602p:plain
240色表示

、、、こうなります。
BGの行がパレット番号に対応しています。
これでわかりましたが、1パレット16色のうち1色は透明色に割り振られています。なので、実質15色です。画面の左端1列がまるごと黒くなっています。
15×16=240色が表現可能なBGの色。背景色が加わった場合は241色になります。

f:id:nicotakuya:20201130141747j:plain
変換前の画像


あと、自作ツールにBMP→BGデータの変換機能を追加してみました。たとえば、このような画像を用意します。これをPhotoshopで解像度を256x224ピクセルに調節。16色に変換してBMPで保存します。

f:id:nicotakuya:20201130141844p:plain
ツールでデータ化

ここで「PC Engine BG」のボタンを押す。
3つのバイナリファイルが生成されるので、先ほどのテストパターンと差し替えます。

f:id:nicotakuya:20201130141924p:plain
BGの表示に成功

PCエンジンエミュレータで実行すると、こうなります。BGにオリジナルの画像を表示することができました。これでPCXファイルが完全に不要になりました
現状の不満点としては、変換ツールが1パレットにしか対応していないので、同時発色が16色のみになっています。
あと、見た目が元画像よりものっぺりしてしまいました。これはパレットのカラーが24bit→9bitに変換されてしまうためです。色がくっ付いてしまったぶん、パレットを無駄に消費してしまいます。
このへんはこれから改善します。

(追記2020/12/3)

f:id:nicotakuya:20201203234339p:plain
同じパターンを飛ばしてVRAMを節約

SPEDITに新機能を追加して、同じ絵柄のパターンは登録をスキップできるようにしました。これでVRAMをいくらか節約できます。チェックボックスで機能のオン/オフが設定できます。

続き
nicotakuya.hatenablog.com