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つですむのですがサンプルという事で。

269_01.png







具体的な指定方法




IOレジスタの$4014を使います。


  1.     ; スプライト描画
  2.     lda #$7 ; スプライトデータは$0700番地にしたので、7を設定
  3.     sta $4014 ; スプライトDMAレジスタにAをストアして、スプライトデータをDMA転送する





ソースの抜粋はこんな感じ。


  1.     ;スプライトの初期表示位置を設定
  2.     lda #100
  3.     sta $0000 ;X座標を$0000に保存
  4.     sta $0001 ;Y座標を$0001に保存
  5.     
  6.     
  7.     ;解像度 256x240
  8.     ; スプライト描画
  9.     
  10.     ;スプライト1
  11.     ;Y座標
  12.     lda $0001 ; Y座標($0001)をロード
  13.     sta $0700 ; Y座標をレジスタにストアする
  14.     
  15.     ;2バイト目 タイルインデクス番号
  16.     lda #$0
  17.     sta $0701
  18.     
  19.     ;3バイト目 8ビットのビットフラグです。スプライトの属性を指定します。
  20.     sta $0702
  21.     
  22.     ;4バイト目 X座標
  23.     lda $0000    ; X座標($0000)をロード
  24.     sta $0703 ; X座標をレジスタにストアする
  25.     ;スプライト2
  26.     ;Y座標
  27.     lda $0001 ; Y座標($0001)をロード
  28.     sta $0704 ; Y座標をレジスタにストアする
  29.     
  30.     ;2バイト目 タイルインデクス番号
  31.     lda #$01
  32.     sta $0705
  33.     
  34.     ;3バイト目 8ビットのビットフラグです。スプライトの属性を指定します。
  35.     lda #$0
  36.     sta $0706
  37.     
  38.     ;4バイト目 X座標
  39.     lda $0000    ; X座標($0000)をロード
  40.     adc #8        ; 8ドット移動
  41.     sta $0707 ; X座標をレジスタにストアする
  42.     
  43.     
  44.     ;スプライト3
  45.     ;Y座標
  46.     lda $0001 ; Y座標($0001)をロード
  47.     adc #8        ; 8ドット移動
  48.     sta $0708 ; Y座標をレジスタにストアする
  49.     
  50.     ;2バイト目 タイルインデクス番号
  51.     lda #$02
  52.     sta $0709
  53.     
  54.     ;3バイト目 8ビットのビットフラグです。スプライトの属性を指定します。
  55.     lda #$0
  56.     sta $070a
  57.     
  58.     ;4バイト目 X座標
  59.     lda $0000    ; X座標($0000)をロード
  60.     sta $070b ; X座標をレジスタにストアする
  61.     ;スプライト4
  62.     ;Y座標
  63.     lda $0001 ; Y座標($0001)をロード
  64.     adc #8        ; 8ドット移動
  65.     sta $070c ; Y座標をレジスタにストアする
  66.     
  67.     ;2バイト目 タイルインデクス番号
  68.     lda #$03
  69.     sta $070d
  70.     
  71.     ;3バイト目 8ビットのビットフラグです。スプライトの属性を指定します。
  72.     lda #$0
  73.     sta $070e
  74.     
  75.     ;4バイト目 X座標
  76.     lda $0000    ; X座標($0000)をロード
  77.     adc #8        ; 8ドット移動
  78.     sta $070f ; X座標をレジスタにストアする
  79. ; スクロール設定
  80.     lda    #$00
  81.     sta    $2005
  82.     sta    $2005
  83. ; スクリーンオン
  84.     lda    #$08
  85.     sta    $2000 ;PPUコントロールレジスタ1
  86.     lda    #$1e
  87.     sta    $2001 ;PPUコントロールレジスタ2
  88. ; 無限ループ
  89. mainloop:
  90.     
  91.     ;ここでコントローラーからの入力を監視
  92.     lda $2002 ; VBlankが発生すると、$20027ビット目が1になります。
  93.     bpl mainloop ; bit70の間は、mainLoopラベルの位置に飛んでループして待ち続けます。
  94.     ; スプライト描画
  95.     lda #$7 ; スプライトデータは$0700番地にしたので、7を設定
  96.     sta $4014 ; スプライトDMAレジスタにAをストアして、スプライトデータをDMA転送する
  97.         
  98.     ; パッドI/Oレジスタの準備
  99.     lda #$01
  100.     sta $4016
  101.     lda #$00
  102.     sta $4016
  103.     ; パッド入力チェック
  104.     lda $4016 ; Aボタンをスキップ
  105.     lda $4016 ; Bボタンをスキップ
  106.     lda $4016 ; Selectボタンをスキップ
  107.     lda $4016 ; Startボタンをスキップ
  108.     lda $4016 ; 上ボタン
  109.     and #1     ; AND #1
  110.     bne UPKEYdown ; 0でないならば押されてるのでUPKeydownへジャンプ
  111.     
  112.     lda $4016 ; 下ボタン
  113.     and #1     ; AND #1
  114.     bne DOWNKEYdown ; 0でないならば押されてるのでDOWNKeydownへジャンプ
  115.     lda $4016 ; 左ボタン
  116.     and #1     ; AND #1
  117.     bne LEFTKEYdown ; 0でないならば押されてるのでLEFTKeydownへジャンプ
  118.     lda $4016 ; 右ボタン
  119.     and #1     ; AND #1
  120.     bne RIGHTKEYdown ; 0でないならば押されてるのでRIGHTKeydownへジャンプ
  121.     jmp NOTHINGdown ; なにも押されていないならばNOTHINGdown
  122. UPKEYdown:
  123.     dec $0001    ; Y座標を1減算。
  124.     jmp NOTHINGdown
  125. DOWNKEYdown:
  126.     inc $0001 ; Y座標を1加算
  127.     jmp NOTHINGdown
  128. LEFTKEYdown:
  129.     dec $0000    ; X座標を1減算
  130.     jmp NOTHINGdown
  131. RIGHTKEYdown:
  132.     inc $0000    ; X座標を1加算
  133.     ; この後NOTHINGdownなのでジャンプする必要無し
  134. NOTHINGdown:
  135.     ;ここで各スプライト座標の再計算
  136.     
  137.     lda $0000 ;X座標取り出し
  138.     ;各スプライトのX座標変更
  139.     sta $0703 ; スプライト1 - X座標
  140.     sta $070b ; スプライト3 - X座標
  141.     adc #8        ; 8ドット移動
  142.     sta $0707 ; スプライト2 - X座標
  143.     sta $070f ; スプライト4 - X座標
  144.     
  145.     lda $0001 ;Y座標取り出し
  146.     ;各スプライトのY座標変更
  147.     sta $0700 ; スプライト1 - Y座標
  148.     sta $0704 ; スプライト2 - Y座標
  149.     adc #8        ; 8ドット移動
  150.     sta $0708 ; スプライト3 - Y座標
  151.     sta $070c ; スプライト4 - Y座標
  152.     jmp    mainloop ; mainLoopの最初に戻る
  153. .endproc




動かしてみると、いい感じでスプライトの塊が移動してくれました。


[広告 ] VPS




今回のソースは、
https://github.com/symfoware/nes_sample/tree/main/src
こちらのsample6においてます。



続きはこちら。
Ubuntuでファミコンプログラム その7(VBlank割り込み)



【参考URL】

ギコ猫でもわかるファミコンプログラミング - 第9章 スプライトDMA
関連記事

コメント

プロフィール

Author:symfo
blog形式だと探しにくいので、まとめサイト作成中です。
https://symfo.web.fc2.com/

PR

検索フォーム

月別アーカイブ