モード7
モード7で、BGを回転・拡大縮小します。
モード7の特徴
モード7では、BG1を1枚だけ、変換行列を使って回転・拡大縮小して表示します(BG)。ほかのモードとはデータの形式が大きく異なります。
| 項目 | 内容 |
|---|---|
| タイルマップ | 128×128タイル、1タイル1バイト(タイル番号のみ) |
| タイルデータ | 256枚、1ピクセル1バイト(256色) |
| VRAMの配置 | $0000~$3FFFの各ワードの下位バイトにタイルマップ、上位バイトにタイルデータ |
データの転送
タイルマップとタイルデータは、同じワードの下位バイトと上位バイトに入るので、VMAINCの設定を変えて別々に転送します。
SEP #$20
REP #$10
; タイルマップ(16KB)を各ワードの下位バイトへ
STZ $2115 ; VMAINC: $2118への書込後にアドレスを1増やす
LDX.w #$0000
STX $2116 ; VMADD = $0000
STZ $4300 ; DMAP0: モード0(1レジスタ)
LDA.b #$18
STA $4301 ; BBAD0: VMDATAL($2118)
LDX.w #Mode7Map&$FFFF
STX $4302
LDA.b #Mode7Map>>16
STA $4304
LDX.w #$4000
STX $4305 ; 16384バイト
LDA.b #$01
STA $420B
; タイルデータ(16KB)を各ワードの上位バイトへ
LDA.b #$80
STA $2115 ; VMAINC: $2119への書込後にアドレスを1増やす
LDX.w #$0000
STX $2116 ; VMADD = $0000
LDA.b #$19
STA $4301 ; BBAD0: VMDATAH($2119)
LDX.w #Mode7Tiles&$FFFF
STX $4302
LDA.b #Mode7Tiles>>16
STA $4304
LDX.w #$4000
STX $4305
LDA.b #$01
STA $420B
設定
LDA.b #$07
STA $2105 ; BGMODE: モード7
STZ $211A ; M7SEL: 範囲外は繰り返し、反転なし
LDA.b #$01
STA $212C ; TM: BG1を表示する
変換行列
変換行列の各要素(M7A~M7D)は8.8の固定小数点で、$0100が1倍です。回転の中心はM7X・M7Yで指定します。どれも下位バイト、上位バイトの順に2回書き込みます。
| 効果 | M7A | M7B | M7C | M7D |
|---|---|---|---|---|
| そのまま | $0100 | 0 | 0 | $0100 |
| 2倍に拡大 | $0080 | 0 | 0 | $0080 |
| 半分に縮小 | $0200 | 0 | 0 | $0200 |
| 角度θだけ回転 | cosθ | sinθ | -sinθ | cosθ |
値を小さくすると拡大、大きくすると縮小になることに注意してください。行列は「画面上の点が、BGのどの点を表示するか」を表しているためです。
回転させる
角度ごとのcos・sinの値(8.8の固定小数点)を表にしておき、NMI処理ルーチンで角度に応じた値を書き込みます。
; $30 の角度(0~255)で回転させる(NMI処理ルーチンの中で)
REP #$30
LDA $30
AND.w #$00FF
ASL A
TAX
LDA.l CosTable,X
SEP #$20
STA $211B ; M7A 下位バイト
XBA
STA $211B ; M7A 上位バイト
XBA
STA $211E ; M7D 下位バイト(M7D = M7A)
XBA
STA $211E ; M7D 上位バイト
REP #$20
LDA.l SinTable,X
SEP #$20
STA $211C ; M7B 下位バイト
XBA
STA $211C ; M7B 上位バイト
XBA ; 上位・下位を元の並びに戻す
REP #$20
EOR.w #$FFFF
INC A ; -sinθ
SEP #$20
STA $211D ; M7C 下位バイト
XBA
STA $211D ; M7C 上位バイト
; 回転の中心を画面の中央にする
LDA.b #128
STA $211F
STZ $211F ; M7X = 128
LDA.b #112
STA $2120
STZ $2120 ; M7Y = 112
CosTable・SinTableは、角度1あたり 360°÷256 で、値を256倍した16ビットの数を256個ずつ並べた表です。ツールなどで計算して作っておきます。
このページのコードで使うMode7Map(mode7map.bin)・Mode7Tiles(mode7tiles.bin)・CosTable・SinTable(sincos.asm)は、サンプルの素材に入っています。
M7X・M7Yは、BGの座標で指定します。上の例はスクロール量(BG1HOFS・BG1VOFS)が0の場合で、BGの(128, 112)が画面の中央に来ています。スクロールしている場合は、画面の中央に来るBGの座標(スクロール量 + 128、スクロール量 + 112)をM7X・M7Yに書き込みます。
| そのまま | 2倍に拡大 | 回転(角度21、約30°) |
|---|---|---|
![]() | ![]() | ![]() |
どれもスクロール量0、回転の中心はBGの(128, 112)です。画面写真は、サンプルの画面にこのページのコードを実行し、エミュレーターで撮ったものです。
奥行きのある床
ラインごとに拡大率を変えると、画面の奥へ向かって遠ざかる床のように見せられます。これには、M7AとM7Dの値をHDMAでラインごとに書き換えます(HDMAを使う)。M7A・M7Dは2回書き込みのレジスタなので、転送モード2を使います。
注意
- モード7のスクロール量は、BG1HOFS・BG1VOFS($210D・$210E)に書き込みます。ほかのモードのBG1のスクロールと同じレジスタです。
- 変換行列のレジスタは、モード7を使っていないときは符号付き乗算器としても使えます。モード7の表示中は、乗算器として使わないでください。


