005849 sprite

Mr.五右衛門のやつ。この基板は 005849 以外にたいした IC が載ってないので、sprite と tile を両方担当している気がする。たぶん。

VRAM

CPU(Z80) から見える RAM は 0x100 word x8bit を2つ持つらしい。この2つのRAMうち1つをレジスタに登録しておいて、指定した RAM のほうを定期的に別のRAMへ取り込むようだ。

attribute RAM は 4word で構成され、先頭 0x30 個の attribute が有効になる。残りの 0x10 個の部分は普通のRAMとして利用可能。

offset.bit
                                • -
0.7:0 charcter ROM address 14:7 1.7 x position 8 1.6 charcter ROM address 15 1.5 y flip 1.4 x flip 1.3:0 palette ROM address 7:4 2.7:0 x position 7:0 3.7:0 y position

sprite の size は 16x16 で固定。内部 offset は 4bit. charcter ROM address は下記となる。

 A15:7  A6  A5  A4:2  A1:0
                                                    • -
ca15:7 oy3 ox3 oy2:0 ox2:1 ca:charcter ROM address oy:offset y ox:offset x

charcter data と ROM

data は 8bit で構成され、 offset0 で bit が選択される。0 なら bit7:4, 1 なら bit3:0 が有効になる。選択された data は palette RAM address 3:0 として使われる。
ROM は databus 8bit の 2つで構成され、ca15 が ROM の選択bitとなる。

palette ROM と color ROM

palette ROM は databus 4bit で構成され、 sprite 用と tile 用に別れて並行に動作する。palette ROM の data 0 の場合は透過となるが、それ以外は color ROM の address となる。

透過状況とレイヤ別のプライオリティを計算して、使用する color RAM の address を選択する。color ROM address の接続は下記となる。

A4  A3:0
              • -
st pd3:0 st:layer (0:sprite, 1:tile) pd:palette ROM data

color ROM data は D/A 変換してモニタに出力される。8bit で blue 2bit, green 3bit, red 3bit.

palette ROM と color ROM を分離するのは謎に感じる。

M72 sprite

この記事もそのうちこっそり消えるかもしれません。

attribute RAM

CPU から見える RAM は 0x200 word x 16 bit。4 word 毎に記載し、0x80 個の attribute を持つことが出来る。sprite renderer に描画処理用の RAM を別に持ち、転送開始レジスタ (main CPU port address 0x0004) を write すると CPU 書き込み用 RAM から描画処理用の RAM へ転送されて、画面が更新される。

offset.bit
                                • -
0.8:0 y position 1.15:0 charcter ROM starting address 20:5 2.15:14 x size 2.13:12 y size 2.11 x flip 2.10 y flip 2.3:0 color RAM address 7:4 3.9:0 x position
  • size は 16 << size となり、16,32,64,128 の 4 通り。
  • 原点からの offset は 0 から 127 の 7bit で構成される。(x,yで2つ)
  • charcter ROM starting address から offset に応じて charcter ROM の address が更新される。051960 とは異なり、 charcter ROM address にも carry が影響する点にから starting とした。

レンダリング途中は offset x, offset y からアドレスを算出するが、下記のように bit 連接してから加算する。

  20:11   10:8   7:5   4   3:0
                                                          • -
9'h00 ox6:4 oy6:4 ox3 oy3:0 ca20:11 ca10:8 ca7:5 0 4'h0 ox:offset x, oy:offset y ca:charcter ROM starting address

flip 時の offset 反転は size によって異なる。size 16 なら bit3:0, size 32 なら bit:4:0 となる。

charcter data と ROM

data は 8x4 bit で構成されて、 offset x 2:0 に応じて bit が選択される。offset 0 なら bit7, offset 7 なら bit0 と msb から左から右へ画素が選択される。

ROM は 8bit の ROM 4 つを1グループとし、4つとも address が共有され、32bit となる。

color RAM と charcter data

各レイヤの透過状況を調べ、描画するレイヤの color RAM address 7:4 と charcter data (4bit) を取得し、 color RAM の address とする。color RAM から得られた data を D/A 変換してモニタへ出力する。

color RAM は 8x3 bit で構成され、 5x3bit だけが使われる(?)。address は下記で構成される。

8   7:4   3:0
                          • -
l cl7:4 cd3:0 l:layer (0:tile, 1:sprite), cl:color RAM address cd:charcter data

wikipedia - ORゲート

http://ja.wikipedia.org/wiki/OR%E3%82%B2%E3%83%BC%E3%83%88

OR ゲートの IC として 4071 のピン配置が貼られている。いまさら OR ゲートを単体で使う場面も少ないこのご時世に一般的だった 7432 ではなく 4071 の図を使っている。さらに 4071 と 7432 のピン配置が同じと読めるような怪しい文面がある。

気になったので英語版を見たら、同じ事が書いてあったのでどっちかを翻訳したらしい。AND ゲートや NOR ゲートでも4000シリーズのピン配置が貼られているが、そんな風に読める文面は書いてない。

いろいろ考えて、このORゲートの記述は直してはいけないことに気づいた。こういった学校でやるような基本的な部分にこんな滑稽な文を書いておくと、学生が何も考えずに wikipedia を丸映しするから、採点側の手間が減るからだ。

StarRuby のパレット機能を使ったその2

051960 の sprite attribute を取り込んで、パレット付き1枚png (512x512 pixel)から(16x16 pixel)チップを切り出してサイズに応じて並べ替えるときに判明したのだが、複数チップを1つの texture に描くので、パレット情報が失われてしまう。

ということで、この作業をする前に1枚pngのパレットを毎回変えるハメになってあまり合理的にいかない。0 番 pixel だけ透過ならいんだが、 0xe番 pixel が shadow bit がある場合だけ shadow が有効という仕様があって、黒い半透明で擬似的に見せようと思ったのにきれいにできない。

いまの状態だと zoom がないからこれだけ作って終わりにしようかな...

051960 のスプライト情報

まずかったらこの項目はそのうち消えます。

VRAM - sprite attribute VRAM

CPU から見える RAM は基板に載ってる databus width 8bit の SRAM で、68000 から使う場合は 16bit のように見えるが、LDS,UDS で A0 を生成して切り換えているので、おそらく byte access 専用。(movep ではなく move.b が使えるのが便利なのかもしれない)

8 byte 単位で 128 個のspriteを管理できると思われる。

CPU から見える RAM は Vblank のタイミングかなにかで、定期的に 051960 に取り込まれて、ASIC 内部RAMか別の RAM へ転送されるものと思われる。このときに sort のようないらないbitは捨てて、 y position みたいなものはレンダリング途中に更新すると思われる。

offset.bit|assingment
                                          • -
0.7 enable (0:hide, 1:visible 0.6:0 priority とか sort とか link とかよばれるもの 1.7:5 size 1.4:0 charcter ROM address 16:13 2.7:0 charcter ROM address 12:5 3.7:0 配線依存 4 から 7 は先日のやつと同じ
  • priority はスプライトの優先度
  • size はスプライトのサイズ (0:16x16, 1:32x16, 2:16x32, 3:32x32, 4:64x32, 5:32x64, 6:64x64, 7:128x128)
  • charcter ROM は後で詳しく記載する
  • 配線依存は基本的に設計毎にことなる部分で、color RAM address だったり、charcter ROM bank だったり、shadow bit だったりばらばら。 offset 3 はよくばらばらにされるが、他のbitも配線を変更する場合があるらしい

(bank は sprite ではなく tile のほうでしたので削除しました)

size と charcter ROM address

size によって charcter ROM address に alignment みたいなものが発生するが、空いた bit は一見不規則に charcter ROM address が振られる。size によって変更される bit と sprite 内の offset は下記になる。

sz A10 A9  A8  A7  A6  A5  A4  A3  A2:0
                                                                                  • -
0 ca10 ca9 ca8 ca7 ca6 ca5|oy3 ox3 oy2:0 1 ca10 ca9 ca8 ca7 ca6|ox4 oy3 ox3 oy2:0 2 ca10 ca9 ca8 ca7|oy4[ca5]oy3 ox3 oy2:0 3 ca10 ca9 ca8 ca7|oy4 ox4 oy3 ox3 oy2:0 4 ca10 ca9 ca8|ox5 oy4 ox4 oy3 ox3 oy2:0 5 ca10 ca9|oy5[ca7]oy4 ox4 oy3 ox3 oy2:0 6 ca10 ca9|oy5 ox5 oy4 ox4 oy3 ox3 oy2:0 7 |oy6 ox6 oy5 ox5 oy4 ox4 oy3 ox3 oy2:0 (sz: size, ox: offset x, oy: offset y, ca: charcter ROM address)

bit 11以降は size による変更はない。

StarRuby のパレット機能を使った

特に難しくなく、リファレンスにあるとおりです。change_pallete で Textcure が再生成されるわけでそれなりのコストがかかる気もするし、そもそもパレットなんて4bitぐらいなので同じ Textcure を 16 通り持つというのもそんなに悪くない気がした。
libpng の場合はパレットに透過,半透明を含めることが出来なかったのでよくわからんが、 StarRuby の場合はそれらも動的には設定しやすかった。

パレット付き PNG ファイルを作る方法

StarRuby は読み込み専用で動的に作ることが出来ないらしい....
キャラクタROMのデータをパレット付きに変換するというのはあまりないみたい実例みたいで、それを満たすようなライブラリはなかった。

というわけで libpng を使った C プログラムを書く。(struct png_work はお察し下さい)

void png_save(struct png_work *s, const char *filename)
{
	FILE *fp = fopen(filename, "wb");
	png_struct *png = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
	png_info *info = png_create_info_struct(png);

	png_init_io(png, fp);

	png_set_compression_level(png, Z_BEST_COMPRESSION);
	png_set_IHDR(
		png, info, s->width, s->height,
		s->bpp, PNG_COLOR_TYPE_PALETTE, PNG_INTERLACE_NONE,
		PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT
	);

	png_set_tRNS(png, info, &s->transport_color, 1, NULL);
	png_set_PLTE(png, info, s->palette, 1 << s->bpp);

	png_write_info(png, info);
	png_set_packing(png);
	png_write_image(png, s->image);
	png_write_end(png, info);
	png_destroy_write_struct(&png, &info);
	fclose(fp);
	
}

s->image はライン毎のポインタ配列であること、そのポインタの中は bpp が 4 なら 0 から 0xf のデータを入れればいいぐらい。png_byte *nanka とかかればわかるものの、png_bytep nanka とかいてポインタ配列に渡すと訳がわからなくなった。慣れというか、自分の経験値が足りない気がした。