Ubuntuでファミコンプログラム その6(DMAを使用したスプライト情報の一括設定)
Ubuntuでファミコンエミュレーターで動くプログラムを作ってみてます。Ubuntuでファミコンプログラム その5(スプライトを動かす)
前回までのソースは、
https://github.com/symfoware/nes_sample/tree/main/src
こちらのsample5においてます。
スプライトDMA
64個のスプライト情報をいちいち変更するの面倒だなと思っていたら、
一括で設定できる「スプライトDMA」という機能があるそうで。
いつものように、ここをじっくり眺めます。
ギコ猫でもわかるファミコンプログラミング - 第9章 スプライトDMA
使用できるメモリ領域0x0000から0x07ffの間に、64個のスプライト情報を格納する
256バイト(0x100)の連続した領域を確保。
その先頭のアドレスを渡すと、一気にスプライト情報を更新してくれるようです。
0x0000から0x07ffの間の0x100ですが、
・0x0000から0x00ffは「ゼロページ」と呼ばれる便利な領域なので使いたくない。
・0x0100から0x01ffは「スタック領域」と呼ばれる、特別な領域なので使いたくない。
実質0x0200から0x07ffの間のどこかを選ぶことになります。
また、先頭のアドレスを渡すとき、アドレス全体ではなくてアドレスの上位2バイトを指定するので、
「0x0300から0x03ff」や、「0x0500から0x05ff」というように、開始がキリ番じゃないとダメです。
なんとなく、使える領域の後ろの方に寄せたかったので、
「0x0700から0x07ff」を使うことにしました。
スプライトデータの用意
8x8のスプライト4つ分を一気に動かすサンプルです。
スプライトデータの領域に、8x8の画像を4つ用意しました。
これを組み合わせてひとつの画像にします。
※この画像なら、上下反転させれば1つですむのですがサンプルという事で。
具体的な指定方法
IOレジスタの$4014を使います。
- ; スプライト描画
- lda #$7 ; スプライトデータは$0700番地にしたので、7を設定
- sta $4014 ; スプライトDMAレジスタにAをストアして、スプライトデータをDMA転送する
ソースの抜粋はこんな感じ。
- ;スプライトの初期表示位置を設定
- lda #100
- sta $0000 ;X座標を$0000に保存
- sta $0001 ;Y座標を$0001に保存
- ;解像度 256x240
- ; スプライト描画
- ;スプライト1
- ;Y座標
- lda $0001 ; Y座標($0001)をロード
- sta $0700 ; Y座標をレジスタにストアする
- ;2バイト目 タイルインデクス番号
- lda #$0
- sta $0701
- ;3バイト目 8ビットのビットフラグです。スプライトの属性を指定します。
- sta $0702
- ;4バイト目 X座標
- lda $0000 ; X座標($0000)をロード
- sta $0703 ; X座標をレジスタにストアする
- ;スプライト2
- ;Y座標
- lda $0001 ; Y座標($0001)をロード
- sta $0704 ; Y座標をレジスタにストアする
- ;2バイト目 タイルインデクス番号
- lda #$01
- sta $0705
- ;3バイト目 8ビットのビットフラグです。スプライトの属性を指定します。
- lda #$0
- sta $0706
- ;4バイト目 X座標
- lda $0000 ; X座標($0000)をロード
- adc #8 ; 8ドット移動
- sta $0707 ; X座標をレジスタにストアする
- ;スプライト3
- ;Y座標
- lda $0001 ; Y座標($0001)をロード
- adc #8 ; 8ドット移動
- sta $0708 ; Y座標をレジスタにストアする
- ;2バイト目 タイルインデクス番号
- lda #$02
- sta $0709
- ;3バイト目 8ビットのビットフラグです。スプライトの属性を指定します。
- lda #$0
- sta $070a
- ;4バイト目 X座標
- lda $0000 ; X座標($0000)をロード
- sta $070b ; X座標をレジスタにストアする
- ;スプライト4
- ;Y座標
- lda $0001 ; Y座標($0001)をロード
- adc #8 ; 8ドット移動
- sta $070c ; Y座標をレジスタにストアする
- ;2バイト目 タイルインデクス番号
- lda #$03
- sta $070d
- ;3バイト目 8ビットのビットフラグです。スプライトの属性を指定します。
- lda #$0
- sta $070e
- ;4バイト目 X座標
- lda $0000 ; X座標($0000)をロード
- adc #8 ; 8ドット移動
- sta $070f ; X座標をレジスタにストアする
- ; スクロール設定
- lda #$00
- sta $2005
- sta $2005
- ; スクリーンオン
- lda #$08
- sta $2000 ;PPUコントロールレジスタ1
- lda #$1e
- sta $2001 ;PPUコントロールレジスタ2
- ; 無限ループ
- mainloop:
- ;ここでコントローラーからの入力を監視
- lda $2002 ; VBlankが発生すると、$2002の7ビット目が1になります。
- bpl mainloop ; bit7が0の間は、mainLoopラベルの位置に飛んでループして待ち続けます。
- ; スプライト描画
- lda #$7 ; スプライトデータは$0700番地にしたので、7を設定
- sta $4014 ; スプライトDMAレジスタにAをストアして、スプライトデータをDMA転送する
- ; パッドI/Oレジスタの準備
- lda #$01
- sta $4016
- lda #$00
- sta $4016
- ; パッド入力チェック
- lda $4016 ; Aボタンをスキップ
- lda $4016 ; Bボタンをスキップ
- lda $4016 ; Selectボタンをスキップ
- lda $4016 ; Startボタンをスキップ
- lda $4016 ; 上ボタン
- and #1 ; AND #1
- bne UPKEYdown ; 0でないならば押されてるのでUPKeydownへジャンプ
- lda $4016 ; 下ボタン
- and #1 ; AND #1
- bne DOWNKEYdown ; 0でないならば押されてるのでDOWNKeydownへジャンプ
- lda $4016 ; 左ボタン
- and #1 ; AND #1
- bne LEFTKEYdown ; 0でないならば押されてるのでLEFTKeydownへジャンプ
- lda $4016 ; 右ボタン
- and #1 ; AND #1
- bne RIGHTKEYdown ; 0でないならば押されてるのでRIGHTKeydownへジャンプ
- jmp NOTHINGdown ; なにも押されていないならばNOTHINGdownへ
- UPKEYdown:
- dec $0001 ; Y座標を1減算。
- jmp NOTHINGdown
- DOWNKEYdown:
- inc $0001 ; Y座標を1加算
- jmp NOTHINGdown
- LEFTKEYdown:
- dec $0000 ; X座標を1減算
- jmp NOTHINGdown
- RIGHTKEYdown:
- inc $0000 ; X座標を1加算
- ; この後NOTHINGdownなのでジャンプする必要無し
- NOTHINGdown:
- ;ここで各スプライト座標の再計算
- lda $0000 ;X座標取り出し
- ;各スプライトのX座標変更
- sta $0703 ; スプライト1 - X座標
- sta $070b ; スプライト3 - X座標
- adc #8 ; 8ドット移動
- sta $0707 ; スプライト2 - X座標
- sta $070f ; スプライト4 - X座標
- lda $0001 ;Y座標取り出し
- ;各スプライトのY座標変更
- sta $0700 ; スプライト1 - Y座標
- sta $0704 ; スプライト2 - Y座標
- adc #8 ; 8ドット移動
- sta $0708 ; スプライト3 - Y座標
- sta $070c ; スプライト4 - Y座標
- jmp mainloop ; mainLoopの最初に戻る
- .endproc
動かしてみると、いい感じでスプライトの塊が移動してくれました。
[広告 ] VPS
今回のソースは、
https://github.com/symfoware/nes_sample/tree/main/src
こちらのsample6においてます。
続きはこちら。
Ubuntuでファミコンプログラム その7(VBlank割り込み)
【参考URL】
ギコ猫でもわかるファミコンプログラミング - 第9章 スプライトDMA
- 関連記事
-
- Ubuntuでファミコンプログラム その8(矩形波サウンド)
- Ubuntuでファミコンプログラム その7(VBlank割り込み)
- Ubuntuでファミコンプログラム その6(DMAを使用したスプライト情報の一括設定)
- Ubuntuでファミコンプログラム その5(スプライトを動かす)
- Ubuntuでファミコンプログラム その4(スプライト)
コメント