ランダムアクセス
目次
6502基本
DATA は、縦座標が 64 個分並んだあと、横座標が 64個、キャラクタ番号が 64 個並びます。
各配列の先頭からの位置が同じものが1組となっています。
LDX #>DATA ; 2
LDA #0 ; 2
STA >0 ; 3
CLC ; 2
LOOP:
; 縦位置を考慮して VRAM の上位バイトを計算
LDY DATA,X ; 4
BMI END ; 3 / 2
LDA SHIFT,Y ; 4
AND #$03 ; 2
ADC #<VRAM ; 2
STA >1 ; 3
; VRAM 下位バイトを計算
LDA SHIFT,Y ; 4
AND #$E0 ; 2
ADC DATA+64,X ;4
TAY; 2
; キャラを書き込む
LDA DATA+128,X ; 4
STA (0),Y ; 6
INX ; 2
BCC LOOP ; 3 / 2
END:
SHIFT:
DB 00, 20, 40, 60, 80, A0, C0, E0
DB 01, 21, 41, 61, 81, A1, C1, E1
DB 02, 22, 42, 62, 82, A2, C2, E2
SHIFT から、24バイトのデータテーブルがあります。
これは、0~24 の数値を、5bit ローテートした値が入っています。
これにより、縦座標の 5bit shift の計算を高速化しています。
ローテートした値の「下位2bit」に VRAM アドレスの上位 8bit を足し、>1 に入れています。
ちなみに、>0 は前処理で 0 を入れた後、常に 0 のままです。
「上位3bit」が、VRAM アドレスの下位バイトに当たります。
こちらはさらに横座標を足して、VRAM アドレスの下位 8bit が完成。
最後に、STA (0),Y でキャラクターの書き込みを行っています。
これは、ゼロページの 0 の値を下位、1 を上位とした 16bit アドレスに、さらに Y を足したアドレスに、A レジスタの値を書き込む命令です。
VRAM の下位アドレス(Yに入れてある)はここで足してしまうため、下位アドレスの >0 は常に 0 にしてあるのです。
ループ内の計算は、一切キャリーを発生しません。
そのため、前処理でキャリーをクリアした後は、足し算前にもキャリーをクリアしていません。
ループ最後の分岐も、「キャリーがクリアなら」を使用していますが、条件分岐ではなく必ずジャンプします。(実行速度は変わらないが、コードが短縮できる)
1キャラクタの書き込みに 44クロック。これを 48回繰り返します。
前処理は 9クロックで、終了時には条件分岐で 7クロック必要です。
44 *48 +9+7 = 2128
総計 2128 クロック。
ちなみに、SHIFT テーブルのサイズを倍増し、48バイトにすると、さらに高速化できます。
詳細は書きませんが総計 1840 クロックになります。
ただ、現時点でも Z80 よりずっと速いので、テーブルを肥大化させるのは自粛しています。
(Z80 に負けそうになった時には 1840 クロック版にします(笑))
16bitテーブル
2014.8.8 午前追記
Z80 に負けそうになったらテーブルを肥大化させる、と書いておいたら、早速その時がやってきました(笑)
いや、自分が作ったヘボプログラムを皆さんが改良してくれるので、非常に楽しいです。
紹介するのも投稿されたもので、単にテーブルを肥大化させただけでなく、さらに高速化されています。
LDX #>DATA ; 2
LDA #0 ; 2
STA >0 ; 3
CLC ; 2
LDY DATA,X ; 4
BMI END ; 3 / 2
LOOP:
LDA SHIFT_HI,Y; 4
STA >1 ; 3
LDA SHIFT_LO,Y; 4
ADC DATA+64,X; 4
TAY ; 2
LDA DATA+128,X; 4
STA (0),Y ; 6
INX ; 2
LDY DATA,X ; 4
BPL LOOP ; 3 / 2
END:
SHIFT_LO:
DB 00, 20, 40, 60, 80, A0, C0, E0
DB 00, 20, 40, 60, 80, A0, C0, E0
DB 00, 20, 40, 60, 80, A0, C0, E0
SHIFT_HI:
DB <VRAM ,<VRAM ,<VRAM ,<VRAM ,<VRAM ,<VRAM ,<VRAM ,<VRAM
DB <VRAM+1,<VRAM+1,<VRAM+1,<VRAM+1,<VRAM+1,<VRAM+1,<VRAM+1,<VRAM+1
DB <VRAM+2,<VRAM+2,<VRAM+2,<VRAM+2,<VRAM+2,<VRAM+2,<VRAM+2,<VRAM+2
ループの位置を2命令だけずらして、条件分岐を高速化しています。
このため、前処理にループの一部だった2命令が増加しています。(ループ内には、末尾にも同等の命令が入っています)
前処理 15クロック。キャラクタ1つの書き込みは 36クロック。
終了判定はループの最後に行われるようになり、終了時は 1クロック減少します。
15 + 36*48 - 1 = 1742
総計で 1742 クロックになっています。