|
1 |
GameFSMの改良 (19) |
ブリッジのコードに怪しいところがあるので、修正中です。さて、オープニング画面を追加したいと思い、bsvコードを書きました。8bitレトロマシンとは思えないくらいの立体感のある映像になりました。
まず画像のロード関数です。元画像はここにあった改造度の高いものを256x256に縮め、さらに色数を4色に落としました。パターンROMにおいて、VRAMに転送するだけですが、ただ転送するのはあまり面白くないので、RLE (run length encoding)を行いました。
元画像はpythonでRLEしましたが、そのデコーダのbsvコードを示します。
// PROM アドレス(1 nibble 単位)
Reg#(PAddr_t) rleAddr <- mkReg(0);
// 展開先の相対座標 (0..255, 0..255)
Reg#(U8) rleX <- mkReg(0);
Reg#(U8) rleY <- mkReg(0);
// 残りピクセル数 256 * 256
Reg#(UInt#(16)) pixelsLeft <- mkReg(0);
// 現在のランの残り長さ (1..256)
Reg#(UInt#(9)) runLen <- mkReg(0);
// 色と長さ nibble
Reg#(Pattern_t) rleColor <- mkReg(0);
Reg#(Pattern_t) rleLenHiNib <- mkReg(0);
Reg#(Pattern_t) rleLenLoNib <- mkReg(0);
// PROM から nibble(Pattern_t) を1つ読み取り、dst に入れ、rleAddr を 1 進める
function Stmt rleNextNibble(Reg#(Pattern_t) dst);
return (seq
action
// PROM アドレスをセット
p_addr <= rleAddr;
endaction
// read timing 調整が必要ならここに noAction を挟む
noAction;
action
// nibble を取り込み
dst <= romdata; // romdata : Pattern_t
rleAddr <= rleAddr + 1; // 次の nibble へ
endaction
endseq);
endfunction
// PROM 上で RLE が始まるニブルアドレス(行256の先頭なら 128*256 など、今は簡易に 256)
`define RLE_START_ADDR 128*256
`define VRAM_WIDTH 256
`define VRAM_HEIGHT 256
function Stmt rleDecode();
return (seq
//------------------------------------------------
// 初期化
//------------------------------------------------
action
// RLE データは PROM の 256 行目から始まる前提
rleAddr <= fromInteger(`RLE_START_ADDR);
// 出力先相対座標
rleX <= 0;
rleY <= 0;
pixelsLeft <= fromInteger(`VRAM_WIDTH * `VRAM_HEIGHT -1);
runLen <= 0;
endaction
//------------------------------------------------
// 全ピクセルを描き終えるまでループ
//------------------------------------------------
while (pixelsLeft != 0) seq
// --- 新しいランを読み込む必要があるなら ---
if (runLen == 0) seq
// color
rleNextNibble(rleColor);
// len_hi
rleNextNibble(rleLenHiNib);
// len_lo
rleNextNibble(rleLenLoNib);
action
UInt#(4) hi = unpack(rleLenHiNib);
UInt#(4) lo = unpack(rleLenLoNib);
// ラン長 L = 16*hi + lo + 1
runLen <= extend(unpack({pack(hi), pack(lo)})) + 1;
endaction
endseq
// --- このランから 1 ピクセル描画 ---
setDot(rleX, rleY, rleColor);
action
pixelsLeft <= pixelsLeft - 1;
runLen <= runLen - 1;
// 128 幅で折り返し
if (rleX == 8'd255) begin
rleX <= 0;
rleY <= rleY + 1;
end
else begin
rleX <= rleX + 1;
end
endaction
endseq // while (pixelsLeft != 0)
endseq);
endfunction
FSM rle_fsm <- mkFSM(rleDecode());
function Stmt runRle();
return (seq
`RUN_FSM(rle_fsm)
endseq);
endfunction