MSX:ダブルバッファリング手法メモ

MSX:ダブルバッファリング手法メモ

ダブルバッファリング : 画面の乱れを抑制するためのテクニック

Double buffering : Anti Flicker display technique.

 

githubにおいてあるメモからの転載

github.com


目次

 

という順番で、ダブルバッファリング手法についてメモしていきます。

Warning 👉 パレットテーブルを使わない!

カラーパレットテーブル という 邪魔者
VRAM全域を無駄なく使用したい場合には、配置を変更できないパレットテーブルが邪魔になります。

このメモは COLOR=(n,r,g,b) や COLOR=RESTORE などのパレット操作BASIC命令を使わない 前提で書かれていますので、もしこれらの命令を使用したい場合は、 各テーブルアドレスの配置に工夫が必要になります。


前置き

問題

毎フレーム画面を書き換えている場合、 VBLANK期間中に処理が収まらないと画面が乱れてしまいます。

特に、スプライトアトリビュートテーブルは おかしな位置におかしなスプライトが表示されるなど、 とても激しい乱れが発生します。

VDPの表示期間中に書き換えると、意図しない中途半端な状態で表示が実行されてしまうためです。

ですので、VRAM書き込みをVBLANK期間内に完了させる必要があるのですが、
実際に、VBLANK期間内に全てのVRAM書き込み処理を収めるのは非常に難しい事が多いです。

Note

スプライトの表示管理

SCREEN4以降のスプライトモード2では、スプライトアトリビュートテーブル+スプライトカラーテーブルへの書き込みが必要なので、 64バイト+512バイトVBLANK期間内に転送する必要があります。

👉 この転送量はかなり厳しめです。
👉 turboRは理論上不可能となっています。

turboRではI/Oを使用したVRAM書き込みがMSX2+以前より遅くなっていますので、 スプライトアトリビュートテーブル+スプライトカラーテーブルの書き込みを VBLANK期間内に収める事が不可能になってしまいました。


対処法

表示切替」または
表示スワップ」または
ダブルバッファリング
と呼ばれる手法を使用します。

この手法を使うと、VBLANK期間外に書き込んでも表示が乱れないようになります。

  1. VRAMの空き領域へ書き込み
  2. 書き込みが終わったら、書き込み終わった領域を表示ベースアドレスに設定する

表示に使用されていない領域に書き込みをすれば、表示期間中であっても表示に悪影響が起きません。

そして全ての書き込みが終わったら表示用アドレスを変更することで瞬時に表示が変化します。

SCREEN5以降の裏ページ書き込み&表示切替テクニックもこの手法に該当します)

VDPはキャラクタ(グラフィック)やスプライトデータを表示する際に参照するVRAMアドレスを指定する機能があります。これをベースアドレス設定と言います。

ベースアドレスの種類は、スプライト(パターンジェネレータ、アトリビュート+カラー)、キャラクタ(パターンジェネレータ、パターンカラー、パターンネーム)などがあります。

→ ダブルバッファ手法のための基礎知識


利点

この手法の優れた点は、通常の処理からの追加コストが低い事です。

追加・変更は

  • 書き込み開始VRAMアドレスの変更
  • 書き込み完了後のVDPレジスタ書き込み(アドレス指定)

のみとなります。

処理の効率化によって、VSYNC待ちが少なく、VSYNC処理が軽くなります。

■ メインループ

  1. メイン処理
  2. VRAM書き込み
  3. VSYNC処理完了待ち

■ VSYNC割り込み

  1. VRAM書き込みまで完了していれば、表示ベースアドレス変更(一瞬)
  2. BGM等の処理(タイミング安定)

ダブルバッファを使わない場合

■ メインループ

  1. メイン処理
  2. VSYNC処理完了待ち

■ VSYNC割り込み

  1. メイン処理が終わっていれば、VRAM転送(VBLANK期間を超えると表示化け)
  2. BGM処理(VRAM転送量によってもたつき

副作用

表示期間中に切り替えても良いのですが、
表示期間中に切り替えるとそのラインを境に表示が切り替わるのでティアリングが発生します。

ティアリングが気になる場合は次のVSYNCを待ってから表示を切り替えます。
ただし、表示の反映が1フレーム遅れます。

また、VRAMの空き容量が必要になります。
VSYNCを待つ間に新しいフレームの描画を行いたい場合、 タイミングによっては、「表示中」「表示待ち」「裏で書き換え」の3つのバッファが必要になる可能性もあります。 (トリプルバッファリング)


基礎知識

テーブル名 内容
パターン ネーム テーブル 画面(X,Y)に表示されるキャラクタ コードのテーブル。
パターン カラー テーブル キャラクタ コード毎の色テーブル または 画面座標毎の色テーブル
パターン ジェネレータ テーブル キャラクタ コード毎のドット パターン テーブル
スプライト アトリビュート テーブル スプライト番号毎の表示情報テーブル
スプライト カラー テーブル スプライト番号毎の色テーブル
スプライト パターン ジェネレータ テーブル スプライト パターン番号毎のドット パターン テーブル
  • 各テーブルは、ベースアドレスをVDPへ設定することで、表示に使用するVRAMアドレスを変更できます。
  • ベースアドレスは画面モードによって、アドレスの設定単位に制限があります。

参考:MSX Datapack wiki計画 4章 V9938の画面モード


カラーパレットテーブル という 邪魔者

VRAMの空き領域をフルに使いたい場合、
(微妙な位置に配置され、移動もできない)カラーパレットテーブルが邪魔になります。

カラーパレットテーブルは本来VDPに必要な領域ではなく、
BASICのCOLOR=(n,r,g,b)命令やCOLOR=RESTORE命令でのパレット操作でのみ使用されます。

これらの命令を使わずに、VDPレジスタ操作で直接カラーパレット設定するようにすれば、 邪魔なカラーパレットテーブルを無視できるようになります。


デフォルトのベースアドレス

参考:MSX Datapack wiki - VRAMマップ

画面モード パターンジェネレータ パターンネーム カラー/ブリンク
SCREEN 0 40行 $0800-$0FFF ($800) $0000-$03BF($3C0) なし
SCREEN 0 80行 $1000-$17FF ($800) $0000-$03BF($3C0) $0800-$090D ($19E)
SCREEN 3 $0000-$07FF ($800) $0800-$0AFF ($300) なし
SCREEN 1 $0000-$07FF ($800) $1800-$1AFF ($300) $2000-$201F ($20)
SCREEN 2 $0000-$17FF ($1800) $1800-$1AFF ($300) $2000-$37FF ($800)
SCREEN 4 $0000-$17FF ($1800) $1800-$1AFF ($300) $2000-$37FF ($800)
SCREEN 5/6 212行 なし $0000-$69FF ($6A00) なし
SCREEN 5/6 192行 なし $0000-$5FFF ($6000) なし
SCREEN 7/8 212行 なし $0000-$D3FF ($D400) なし
SCREEN 7/8 192行 なし $0000-$BFFF ($C000) なし
画面モード スプライトアトリビュート スプライトパターン スプライトカラー
SCREEN 0 なし なし なし
SCREEN 3 $1B00-$1B7F ($80) $3800-$3FFF ($800) なし
SCREEN 1 $1B00-$1B7F ($80) $3800-$3FFF ($800) なし
SCREEN 2 $1B00-$1B7F ($80) $3800-$3FFF ($800) なし
SCREEN 4 $1E00-$1E7F ($80) $3800-$3FFF ($800) $1C00-$1DFF ($200)
SCREEN 5/6 $7600-$767F ($80) $7800-$7FFF ($800) $7400-$75FF ($200)
SCREEN 7/8 $FA00-$FA7F ($80) $F000-$F7FF ($800) $F800-$F9FF ($200)

※ SCREEN9SCREEN5/6と同じ
※ SCREEN10/11/12SCREEN7/8と同じ


ベースアドレスの設定可能な単位

参考:MSX Datapack wiki - V9938の画面モード

画面モード パターンジェネレータ パターンネーム カラー/ブリンク
SCREEN 0 40行 $800 $400 なし
SCREEN 0 80行 $800 $1000 $200
SCREEN 3 $800 $400 なし
SCREEN 1 $800 $400 $40
SCREEN 2 $800 $400 $2000
SCREEN 4 $800 $400 $2000
SCREEN 5/6 なし $8000 なし
SCREEN 7/8 なし $10000 なし

参考:MSX Datapack wiki - VDP - レジスタの機能

スプライトモード スプライトアトリビュート スプライトパターン スプライトカラー
スプライトモード 1 $80 $800 なし
スプライトモード 2 $400 * n + $200 $800 $400

BASICでの書き込み先の変更

アセンブラであれば書き込み先アドレスは任意で指定していますが、
BASICは各命令の書き込み先を変更する命令はSET PAGEしかありません。

ですが、ワークエリアの値を変更することでBASIC命令の書き込み先VRAMアドレスを変更できます。

⚠️ ただし、パターンカラーテーブルについてはBASICからの書き込み先変更方法がわかりません。

名称 アドレス サイズ 内容
NAMBAS $F922 2 現在のパターンネームテーブルのベースアドレス
CGPBAS $F924 2 現在のパターンジェネレータテーブルのベースアドレス
PATBAS $F926 2 現在のスプライトジェネレータテーブルのベースアドレス
ATRBAS $F928 2 現在のスプライトアトリビュートテーブルのベースアドレス

👉 スプライトカラーテーブルはスプライトアトリビュートテーブルと連動します。
スプライトアトリビュートテーブル - $200になる)

例)書き込み先パターンネームテーブルを&H2000にしたい場合は、
POKE &HF922,0:POKE &HF923,&H20


スプライト表示

表示座標X、Y、表示パターン番号、表示色について、まとめて表示変更する場合。


スプライトモード1 - SCREEN1/2/3

スプライトモード1ではスプライトアトリビュートテーブルのみを操作すればよいので簡単です。

■ スプライトアトリビュートテーブル

レジスタ bit7 bit6 bit5 bit4 bit3 bit2 bit1 bit0 計算式
VDP R#5 A14 A13 A12 A11 A10 A9 A8 A7 (ad / $80) AND $FF
VDP R#11 0 0 0 0 0 0 A16 A15 ad / $8000
  • サイズは32*4=128$80バイト。
  • ベースアドレスの単位は$80バイト。

ベースアドレスは
パターンネームテーブルもダブルバッファにすることを考慮すると、
$1B00$1F00を使うのが楽ではないでしょうか。

  • $1B00 : R#5=$36,R#11=0
  • $1F00 : R#5=$3E,R#11=0
' ** BASIC SAMPLE **
' PG:ページ番号
' PG=0 : base address = &H1B00
' PG=1 : base address = &H1F00

VDP(5)=&H36+PG*8
VDP(12)=0

'※ VDP R#11 は BASICでは VDP(12)
'    (VDP S#0 が VDP(8) なので以降は番号が1つずれる)
 
; ** ASM SAMPLE **
WRTVDP:		equ	$0047
;===============================================
;    change sprite attribute base address 
;===============================================
;	in	a = page no
;		    0 : base address = $1B00
;		    1 : base address = $1F00
CHG_SPRATR:	add	a,a
		add	a,a
		add	a,a	; a = PAGE * 8
		add	a,$36	; a = $36 + PAGE * 8
		ld	b,a
		ld	c,5
		call	WRTVDP
		xor	a
		ld	c,11
		call	WRTVDP
		ret
 

スプライトモード2

スプライトモード2の場合、スプライトカラーテーブルが別に必要で、データサイズが大きいのがネックになります。

■ スプライトアトリビュートテーブル

レジスタ bit7 bit6 bit5 bit4 bit3 bit2 bit1 bit0 計算式
VDP R#5 A14 A13 A12 A11 A10 1 1 1 ((ad / $80) AND $FF) OR 7
VDP R#11 0 0 0 0 0 0 A16 A15 ad / $8000
  • サイズは32*4=128$80バイト。
  • ベースアドレスは$200を先頭に$400単位。 → $200+$400 * n

■ スプライトカラーテーブル

  • サイズは32*16=512$200
  • ベースアドレスはスプライトアトリビュートテーブル - $200

スプライトカラーテーブルはスプライト番号に対応して16バイトずつ。

Warning ※ スプライトパターン番号ではなくスプライト番号に対応する


スプライトモード2 - SCREEN4

VRAM 16KB($0000 ~ $4000)の範囲ではVRAMの空き領域がないので、ダブルバッファを確保することはできません。
ですが、MSX2以降の機能なのでVRAMは最低でも64KB($0000 ~ $FFFF)が使えます。

単純に+$4000するのが簡単かもしれません。

  • $1E00 : R#5=$3F,R#11=0
  • $5E00 : R#5=$BF,R#11=0
' ** BASIC SAMPLE **
' PG:ページ番号
' PG=0 : atr = &H1E00, color = &H1C00
' PG=1 : atr = &H5E00, color = &H5C00

VDP(5)=&H3F+PG*&H80
VDP(12)=0

'※ VDP R#11 は BASICでは VDP(12)
'    (VDP S#0 が VDP(8) なので以降は番号が1つずれる)
 
; ** ASM SAMPLE **
WRTVDP:		equ	$0047
;===============================================
;    change sprite attribute base address 
;===============================================
;	in	a = page no
;		    0 : atr = $1B00, color = $1C00
;		    1 : atr = $1C00, color = $5C00
CHG_SPRATR:	rlca		; a = a * $80
		add	a,$3F	; a = $3F + PAGE * $80
		ld	b,a
		ld	c,5
		call	WRTVDP
		xor	a
		ld	c,11
		call	WRTVDP
		ret
 

スプライトモード2 - SCREEN5/6/9 (212ライン)

縦スクロールを使わない場合、
ピクセルデータが $0000 ~ $69FF の範囲だけなので、

  • $7200 : R#5=$E7,R#11=0
  • $7600 : R#5=$EF,R#11=0(デフォルト)

を使用することができます。

' ** BASIC SAMPLE 1 **
' PG:ページ番号
' PG=0 : atr = &H7600, color = &H7400
' PG=1 : atr = &H7200, color = &H7000

VDP(5)=&HEF-PG*8
VDP(12)=1 ' +&H8000

'※ VDP R#11 は BASICでは VDP(12)
'    (VDP S#0 が VDP(8) なので以降は番号が1つずれる)
 
; ** ASM SAMPLE 1 **
WRTVDP:		equ	$0047
;===============================================
;    change sprite attribute base address 
;===============================================
;	in	a = page no
;		    0 : atr = $7600, color = $7400
;		    1 : atr = $7200, color = $7000
CHG_SPRATR:	add	a,a
		add	a,a
		add	a,a	; a = PAGE * 8
		cpl		; a = -PAGE * 8
		add	a,$EF	; a = $EF - PAGE * 8
		ld	b,a
		ld	c,5
		call	WRTVDP
		xor	a
		ld	c,11
		call	WRTVDP
		ret
 

スプライトモード2 - SCREEN5/6/9 (256ライン)

縦スクロールで256ライン全てを使う場合、
ピクセル表示だけで $0000 ~ $7FFF まで ページ0の範囲を全て使用してしまうので、 ページ0にスプライトテーブルを配置することができません。

この場合は、別ページにスプライトテーブルを確保します。

  • $B200 : R#5=$E7,R#11=1
  • $B600 : R#5=$EF,R#11=1(デフォルト+$8000)
' ** BASIC SAMPLE 2 **
' PG:ページ番号
' PG=0 : atr = &HB600, color = &HB400
' PG=1 : atr = &HB200, color = &HB000

VDP(5)=&HEF-PG*8
VDP(12)=1 ' +&H8000

'※ VDP R#11 は BASICでは VDP(12)
'    (VDP S#0 が VDP(8) なので以降は番号が1つずれる)
 
; ** ASM SAMPLE 2 **
WRTVDP:		equ	$0047
;===============================================
;    change sprite attribute base address 
;===============================================
;	in	a = page no
;		    0 : atr = $B600, color = $B400
;		    1 : atr = $B200, color = $B000
CHG_SPRATR:	add	a,a
		add	a,a
		add	a,a	; a = PAGE * 8
		cpl		; a = -PAGE * 8
		add	a,$EF	; a = $EF - PAGE * 8
		ld	b,a
		ld	c,5
		call	WRTVDP
		ld	a,1	; +$8000
		ld	c,11
		call	WRTVDP
		ret
 

スプライトモード2 - SCREEN7/8/9/10/11/12 (212ライン)

縦スクロールを使わない場合、
ピクセルデータが $0000 ~ $D3FF の範囲なので、

  • $FA00 : R#5=$F7,R#11=1(デフォルト)
  • $FE00 : R#5=$FF,R#11=1

を使用することができます。

' ** BASIC SAMPLE 1 **
' PG:ページ番号
' PG=0 : atr = &HFA00, color = &HF800
' PG=1 : atr = &HFE00, color = &HFC00

VDP(5)=&HF7+PG*8
VDP(12)=1 ' +&H8000

'※ VDP R#11 は BASICでは VDP(12)
'    (VDP S#0 が VDP(8) なので以降は番号が1つずれる)
 
; ** ASM SAMPLE 1 **
WRTVDP:		equ	$0047
;===============================================
;    change sprite attribute base address 
;===============================================
;	in	a = page no
;		    0 : atr = $FA00, color = $F800
;		    1 : atr = $FE00, color = $FC00
CHG_SPRATR:	add	a,a
		add	a,a
		add	a,a	; a = PAGE * 8
		add	a,$F7	; a = $F7 + PAGE * 8
		ld	b,a
		ld	c,5
		call	WRTVDP
		ld	a,1	; +$8000
		ld	c,11
		call	WRTVDP
		ret
 

スプライトモード2 - SCREEN7/8/9/10/11/12 (256ライン)

縦スクロールを使用する場合、
ピクセルデータだけで $0000 ~ $FFFF まで ページ0の範囲を全て使用してしまうので、 ページ0にスプライトテーブルを配置することができません。

この場合は、別ページにスプライトテーブルを確保します。

  • $1FA00 : R#5=$F7,R#11=3(デフォルト+$10000)
  • $1FE00 : R#5=$FF,R#11=3
' ** BASIC SAMPLE 1 **
' PG:ページ番号
' PG=0 : atr = &H1FA00, color = &H1F800
' PG=1 : atr = &H1FE00, color = &H1FC00

VDP(5)=&HF7+PG*8
VDP(12)=3 ' +&H18000

'※ VDP R#11 は BASICでは VDP(12)
'    (VDP S#0 が VDP(8) なので以降は番号が1つずれる)
 
; ** ASM SAMPLE 1 **
WRTVDP:		equ	$0047
;===============================================
;    change sprite attribute base address 
;===============================================
;	in	a = page no
;		    0 : atr = $1FA00, color = $1F800
;		    1 : atr = $1FE00, color = $1FC00
CHG_SPRATR:	add	a,a
		add	a,a
		add	a,a	; a = PAGE * 8
		add	a,$F7	; a = $F7 + PAGE * 8
		ld	b,a
		ld	c,5
		call	WRTVDP
		ld	a,3	; +$18000
		ld	c,11
		call	WRTVDP
		ret
 

スプライトパターンデータ書き換え

■ スプライト パターン ジェネレータ テーブル(参考用)

レジスタ bit7 bit6 bit5 bit4 bit3 bit2 bit1 bit0 計算式
VDP R#6 0 0 A16 A15 A14 A13 A12 A11 ad / $800

スプライトパターンジェネレータの切り替え手法はベースアドレスの変更ではなく、
スプライトパターンの数がスプライト同時表示可能数の2倍以上なのを利用して、 半分ずつ使用します。

16x16の場合パターン64個なので、
32個*2ページのパターンバッファとして扱い、
スプライト番号ひとつにつき表示パターン番号と作業用(非表示)パターン番号の2個を割り当てる。 という手法を紹介します。

全部を毎回書き換えても良いのですが、 32個のワークを用意して個別に表示に使用するパターン番号を管理するのが良いかと思います。

BASICでの例

前準備

DIM PT(31)
 

パターンNを書き換えたら

PT(N)=(PT(N)+32) AND 63
 

表示例

PUTSPRITE P,(X(P),Y(P)),C(P),PT(P)
 

8x8の場合は、64番以降は固定パターンなどとするとよいかもしれません。


テキスト/キャラ表示

キャラクタコードテーブルのダブルバッファリングについて。

テキスト/キャラ表示 - SCREEN 0/1/2/3/4

※ SCREEN0はWIDTH40の場合。

■ パターン ネーム テーブル

レジスタ bit7 bit6 bit5 bit4 bit3 bit2 bit1 bit0 計算式
VDP R#2 0 A16 A15 A14 A13 A12 A11 A10 ad / $400

参考例)

画面モード 基本 備考
SCREEN 0 $0000 : R#2=$00 $0400 : R#2=$01 追加で$1000 + $400 * n の 12個(計14個)
SCREEN 1 $1800 : R#2=$06 $1C00 : R#2=$07 $800 + $400 * n で 計12個
SCREEN 2 $1800 : R#2=$06 $1C00 : R#2=$07 空き領域に余裕がない
SCREEN 3 $0000 : R#2=$00 $0C00 : R#2=$30 $800 + $400 * n で 12個確保可能
SCREEN 4 $1800 : R#2=$06 $5800 : R#2=$16 スプライトと同じく +$4000 を使用する

テキスト/キャラ表示 - SCREEN 0 WIDTH80

■ パターン ネーム テーブル

レジスタ bit7 bit6 bit5 bit4 bit3 bit2 bit1 bit0 計算式
VDP R#2 0 A16 A15 A14 A13 A12 1 1 ad / $1000 OR 3

設定可能なアドレスは

  • $0000 : R#2=$03
  • $1000 : R#2=$07
  • $2000 : R#2=$0B
  • $3000 : R#2=$0F

ですが、
パターンジェネレータテーブルがあるので $1000 は使えません。
$1000も使いたい場合は、パターンジェネレータテーブルを移動させてください。

パターン ジェネレータ テーブルを移動させる場合
候補は

  • $1800 : R#4=$03
  • $2800 : R#4=$05
  • $3800 : R#4=$07

になります。

Warning
※ パターン ジェネレータに設定したアドレス-$800の位置はパターン ネーム テーブルには使用できません。

■ カラー(ブリンク) テーブル (SCREEN 0 WIDTH 80)

レジスタ bit7 bit6 bit5 bit4 bit3 bit2 bit1 bit0 計算式
VDP R#3 A13 A12 A11 A10 A9 1 1 1 ad / $40 OR 3
VDP R#10 0 0 0 0 0 A16 A15 A14 ad / &H4000
  • サイズは$19E
  • 設定単位は$200

カラー(ブリンク)テーブルも座標に紐づけられているので、
こちらもダブルバッファにする場合があります。

候補は

  • $800 : R#4=$23, R#10=0
  • $A00 : R#4=$27, R#10=0

ビットマップ表示 - SCREEN 5/6/9

■ パターン ネーム テーブル

レジスタ bit7 bit6 bit5 bit4 bit3 bit2 bit1 bit0 計算式
VDP R#2 0 A16 A15 1 1 1 1 1 ad / $8000

BASICならSET PAGE命令で簡単に管理可能です。

ビットマップ表示 - SCREEN 7/8/10/11/12

■ パターン ネーム テーブル

レジスタ bit7 bit6 bit5 bit4 bit3 bit2 bit1 bit0 計算式
VDP R#2 0 A16 1 1 1 1 1 1 ad / $10000

BASICならSET PAGE命令で簡単に管理可能です。


キャラクタパターン書き換え

■ パターン ジェネレータ テーブル (SCREEN 0/1/3)

レジスタ bit7 bit6 bit5 bit4 bit3 bit2 bit1 bit0 計算式
VDP R#4 0 0 A16 A15 A14 A13 A12 A11 ad / $800

■ パターン ジェネレータ テーブル (SCREEN 2/4)

レジスタ bit7 bit6 bit5 bit4 bit3 bit2 bit1 bit0 計算式
VDP R#4 0 0 A16 A15 A14 A13 1 1 INT(ad / $2000) * 4 + 3
  • VRAMに余裕があるのはSCREEN 0, 1, 3 のみです。
  • SCREEN2/4はA12,A11は0扱いで、8KByte($2000)単位での指定になります。
  • SCREEN 4 は、VRAMが 64KB 以上あるので、割と自由です。

参考例)

画面モード 基本 備考
SCREEN 0 width 40 $0800 : R#4=$01 $1000 : R#4=$02 余裕があるので良い感じに配置する
SCREEN 0 width 80 $1000 : R#4=$02 $1800 : R#4=$03 $800 + $1000 * n が安定
SCREEN 1 $3800 : R#4=$07 $3000 : R#4=$06 多少余裕あり
SCREEN 2 $3800 : R#4=$07 無理 空き領域に余裕がない
SCREEN 3 $3800 : R#4=$07 $3000 : R#4=$06 多少余裕あり
SCREEN 4 $3800 : R#4=$07 $7380 : R#4=$0F スプライトと同じく +$4000 を使用する

■ カラー テーブル (SCREEN 1)

レジスタ bit7 bit6 bit5 bit4 bit3 bit2 bit1 bit0 計算式
VDP R#3 A13 A12 A11 A10 A9 A8 A7 A6 ad / $40
VDP R#10 0 0 0 0 0 A16 A15 A14 ad / $4000

SCREEN1の場合、カラーテーブルもダブルバッファにする事があるかもしれません。

  • 8キャラ毎に色を設定するので、サイズは256/8=32$20
  • 設定単位は$40

候補は、

  • $2000 : R#3=$80, R#10=0
  • $2040 : R#3=$81, R#10=0

■ カラー テーブル (SCREEN 2/4)

レジスタ bit7 bit6 bit5 bit4 bit3 bit2 bit1 bit0 計算式
VDP R#3 A13 1 1 1 1 1 1 1 INT(ad / $2000) * $80 + $7F
VDP R#10 0 0 0 0 0 A16 A15 A14 ad / $4000
  • SCREEN2/4の場合はパターンジェネレータ同様に8KByte($2000)単位での指定。
  • SCREEN2では余剰領域が無さ過ぎて複数用意するのは厳しいと思います。
  • SCREEN4であれば+$4000を利用する等が考えられます。

SAMPLE - スプライトモード2 サンプル

Warning Sensitive Contets ※ R15注意 https://github.com/uniskie/MSX_MISC_TOOLS/tree/main/LOADSRD/samples/.sensitive/KUONAI

1ラインにスプライトが8個以上並んでも消えたままにならずに点滅するようにしたサンプル。

事例紹介