引っ掛かったところ


ゆるゆるファミコン・NESの開発を進めていますが、ここまで良く分からなくて躓いたところをまとめておきます。
※初心者なので、まぁ、簡単なところで引っ掛かってます。

■ エミュレーター関係
SRAM を使うときは、iNES ヘッダのROMコントロールを書き換えること。
NES研究所様のサンプル だとこんな感じになっているので、

; iNESヘッダ
.segment "HEADER"
  .byte $4E, $45, $53, $1A  ; "NES" Header
  .byte $02           ; PRG-BANKS
  .byte $01           ; CHR-BANKS
  .byte $01           ; Vetrical Mirror
  .byte $00           ;
  .byte $00, $00, $00, $00  ;
  .byte $00, $00, $00, $00  ;


こう変える。

; iNESヘッダ
.segment "HEADER"
  .byte $4E, $45, $53, $1A  ; "NES" Header
  .byte $02           ; PRG-BANKS
  .byte $01           ; CHR-BANKS
  .byte $03           ; Vetrical Mirror   ← b1 を立てる
  .byte $00           ;
  .byte $00, $00, $00, $00  ;
  .byte $00, $00, $00, $00  ;


内容については、こちら が詳しかったです。
この設定が分からなかったおかげで、nestopia では動かず、悩むこと数日・・・。


■ 初期化
電源投入時(リセット時)には CPU と VDP が同時に起動するとは限らないため、$2002 の b7 をリセット(0)したした後に、$2002 の b7 に「1」がセットされるの2回待たなければいけない。


■ コントローラー
デルタ・モジュレーション音源(DMC)を使う場合、読み込んだコントローラーの値が2回連続して同じ値になるまで読み込み続けるべし。
※DMC を使うとコントローラーの値にエラーが出ることがあるそうで、同値を2回連続で読みこめば正しい値として使ってよしみたいなことらしい。

コントローラーIIの読み込み、

  lda #1
  sta $4016
  lda #0
  sta $4016
  lda $4017


うっかり、$4017 に1 & 0 をセットしたら、ナゼか三角波のコントロールが利かなくなってしまった。
ちゃんとポートには正しい値を書き込んでいたが、鳴りっぱなしになるか、音が出ないかのどちらか。
これが判明するまで1日潰す。


■ VRAM
VRAM に書き込んだあとは、スクロール値をリセットすること。
スクロールは使わない場合は、こんな感じで処理。

  lda #0
  sta $2005
  sta $2005


VRAM は Vblank 中に転送するので、転送量に限度がある。これを超えると画面レイアウトが崩れる。
大体、 32バイト程度が限度。

グラフィック処理は、Vblankのできるだけ最初のほうで行わなわなくていけない。
処理落ちすると、VRAMの書き換えが間に合わなくなり、予期せぬ箇所を書き換えちゃったりする。


■ スプライト
ネット検索してみると、VRAM 転送と同じように $2003 にアドレス、$2004 にデータを書き込むような記述も見受けられますが、どうやらそんな必要はなく、NMI の先頭に近い箇所(511.9マシンサイクル以内)に $4014 で指定するスプライトのセグメント($2 なら、$200~$2ff)の領域に直接書き込めばOKみたいです。
$200~$2ffに直接、スプライトの情報を書き込んだあと、$4014 に書き込むと DMA 転送されるようです。
※$2003 には $00 以外は書き込んではいけないみたいなので、全キャラ書き換えるとき以外は使いづらいですしね。


■ サウンド
矩形波2チャンネルと三角波1チャンネルの計3チャンネルは、$4003、$4007、$400b に周波数データの上位バイトを書き込むと再生のトリガーが掛かります。
しかし、毎回書き込むとノイズが発生するため、上位バイトに変化があったときだけ書き込むようにする。

三角波を無音にしたい場合は、$4008 の長さデータ b0 ~ b6 を 0 にする。連続音指定の場合は $80 にすれば無音になる。
また、三角波には音量指定がないので、連続音を再生するときは長さデータ b0 ~ b6 に適当な値をセットする。
※0以外なら再生。

三角波で空きポートになっている $4009 (矩形波ではスイープ値指定用)、書き込んでも影響なさそげ。
ので、$4008 (発音・無音)以外の周波数の処理は、矩形波と共通でも大丈夫かも。

ノイズ・チャンネルのトリガーは、長さデータの書き込みポート $400f で行いますが、連続音の場合、$00 の書き込みでOK。

DMC の再生手順としては、$4015 で DMC を一旦ディゼイブルにして、$4010、$4012、$4014 をセットしたあと、$4015 で DMC をイネーブルにする。

周波数の計算方法
CPUクロック周波数/(再生したい音程の周波数×32)-1
CPUクロック周波数はファミコンだと、1790000 らしい。

デルタモジュレーションのデータについて
$4013 に送るデータの長さ(量)の指定データは、実際の容量を $10 で割る。
$200 なら $20 なので、簡単。

$4012 に送るデータの先頭アドレスの指定データは、実際のアドレスを の上位2bitをマスク(AND $3fff)して、$40 で割る。
$c200 なら、8 。

■ 割り込み
この辺も全然分からなくて、NMI でレジスタ退避したあとで、$2000 の b7に0を書き込んで割り込み禁止→ VBLANK中の処理→ $2000 の b7に1を書き込んで割り込み許可、という処理にしていたんだけど、それではダメで、$2002 を読み出して、割り込みフラグをリセットしなくてならなった模様。
割り込み関係はいくつかフラグや設定ポートがあるので理解するのが難しい。
知人のファミコン開発経験者に直接尋ねて分かりました。

スポンサーサイト

分からぬ


というわけで、粛々と開発を進めてみてはいるものの、FCEUX、G-NES などのデバッガやチート機能が付いているエミュでは動くのだけど、nestopia では動かない怪現象。

聞くところによると、nestopia が実機に近い動作をしているらしいので、コヤツで動かないと話にならないらしい。
けど、nestopia にはデバッガ機能がついていないので、何が原因で動かないのか調べられないというジレンマ。
まぁ、地道に潰していくしかないだろうなぁ。

しかし、アセンブラは、JAVAやCなどの高級言語を使うときに比べて時間が掛かるなぁ。
あっという間に一日が終ってしまう。
まぁ、高級言語の場合はどちらというと、ライブラリーがあるのが強みなんだろうけど。

あと没頭度も高い。
これは面白いということなのかも知れない。

しかし、これ、お金になるのかね?

そんなあったっけ?


というわけで、cc65 を使ってアセンブラでファミコン開発をしようというプロジェクト(?)、ただ今、勉強中なのですが、色々と分かってきたことをまとめておく。
備忘録。

まずは資料的なものから。

ファミコン(NES) の仕様などは、こちらのサイトに詳しかったです。
NES on FPGA
※正式なサイト名が分からず・・・、すみません。
こちらの、「仕様」の下のリンクが各機能の仕様になってます。

cc65 の仕様に関してはこちら(英語だけど、箇条書きだし、使用例が出てるので、雰囲気は分かるかも)。
c65 Users Guide

6502 のニーモニックはこちら
NES 研究室 -6502

cc65 を使う上で、メモリー管理(割り当て)を行う.cfgファイルについては、以下が詳しいみたいなのですが、いかんせん英語。
cc65 -Configuration files


というわけで、事始め的にプログラムを始めてみたんだけど、アドレッシングを忘れていて冷や汗。
なぜか、Z80とかV30系のアドレッシングで考えてしまう。
設計できねー。

そして忘れていたこと。

・サウンドポートを毎回書き換えると、同値でもノイズ出たんだっけ?
・BG を書き換えたあとにスクロール値をセットし直さないとポジションずれるとかあったっけ?

まだまだですなぁ、先は長い。

始めてみる


わらしべ長者計画も、なかなか上手くいかないので、新たに何か売るものないかなぁ? と、また変なことに手を染めてみるテスト。

海外で色んなプラット・フォームで動く家庭用ゲーム機のエミュレータが無料で配布されているので、それじゃ、ファミコンのROMでも作ってみようかと。
まぁ、ゲームになるとハードルが上がりまくるので、サウンド関係だけでも何とかならないかと。

というわけで、ネット検索してみると、NES研究室 さんとか、ギコ猫でもわかるファミコンプログラミング さんとかに開発方法が詳しく出ているぞ、らしいので、早速、斜め読みして、開発環境を整える。

選択した開発ツールは以下の通り。

・アセンブラ:cc65
・グラフィックツール:YY-CHR
・エミュレーター/デバッガ:fceux

Windows には、MAKE が必要ということなので、Make for Windows をインストール。
※今回は珍しく、Windows で開発。

NES研究所さんから サンプルプログラム をダウンロードして、コマンド・プロンプトを立ち上げて、cd \xxxx\sample1 とディレクトリーを変更して、make したら sample1.nes が出来ました。

しかし、VM で Windows を使っているワタクシ、c: 以外のディスクにsample1フォルダを移動したら、CMD では UNC パスは現在のディレクトリーとしてサポートされません。と表示されてディレクトリーの移動が出来なくなってしまった。

こちらに変更方法が出ていた ので、早速、実行。
pushd (UNCパス)
で、変更したら、make でいけました。

その後、cc65 の使い方などを調べているのですが、どうも Cコンパイラとしての使うのが主流のようで、アセンブラの記述に関する資料がとても少ない。
あと、 メモリマップなどを指定する .cfg ファイル の記述が(ワタシには)理解にしづらい上に、資料に英語が多いのも使いづらいなぁ、などと。
コンフィグの記述は、NESASM の分かりやすいんですよね。

というわけで、やる気スイッチをオンにすべく、新たにカテゴリーを作ってみたわけですが・・・。