NES Sound Format version 2.0 ※ NSF version 2.0は、まだ標準化されていません。   あくまでも、"nesdev"で議論されていた内容を翻訳してまとめただけです。   最終的な仕様がこの通りになるかは、保証しません。 ヘッダの構成: ━━━━━━━━━━━━ オフセット バイト数 内容 --------------------------- 0000 5 STRING "NESM",01Ah ; NESサウンドフォーマットファイルを示します。 0005 1 BYTE バージョン番号 (現在 01h / NSF2 02h) 0006 1 BYTE 曲数 (1 = 1曲、2 = 2曲...) 0007 1 BYTE 開始曲 (1 = 最初の曲、2 = 次の曲...) 0008 2 WORD (LO/HI) 読み込むデータのアドレス (8000-FFFF) 000A 2 WORD (LO/HI) 初期化するデータのアドレス (8000-FFFF) 000C 2 WORD (LO/HI) 再生するデータのアドレス (8000-FFFF) 000E 32 STRING 曲名(NULL終端) 002E 32 STRING 作曲者(NULL終端) 004E 32 STRING 著作権所有者(NULL終端) 006E 2 WORD (LO/HI) 1/1000000秒単位の速さ NTSC (テキスト参照) 0070 8 BYTE バンクスイッチ初期化値 (テキスト及びFDSの項を参照) 0078 2 WORD (LO/HI) 1/1000000秒単位の速さ PAL (テキスト参照) 007A 1 BYTE PAL/NTSC ビット: bit 0: クリアされていれば NTSC bit 0: セットされていれば PAL bit 1: セットされていれば PAL/NTSC両方 bits 2-7: 未使用。必ず 0 にすること。 007B 1 BYTE 拡張音源チップサポート bit 0: セットされていれば VRC6 が使用されています。 bit 1: セットされていれば VRC7 が使用されています。 bit 2: セットされていれば FDS音源が使用されています。 bit 3: セットされていれば MMC5 audio が使用されています。 bit 4: セットされていれば Namco 106 が使用されています。 bit 5: セットされていれば Sunsoft FME-07 が使用されています。 bits 6,7: 今後の拡張用。必ず 0 にすること。 007C 4 BYTE 拡張フラグ(現行のNSF 1.0 では 00h にする事) bit 0: セットされていれば 割り込みIRQ(ベクター0FFFEh)の使用を許可する。 bit 1: セットされていれば 初期化ルーチン(ヘッダーの0Ah)で戻らない事を許可する。 bit 2: セットされていれば 再生ルーチン(ヘッダーの0Ch)を無効にする。 bit 3-6: 未使用。必ず 0 にすること。 bit 7: セットされていれば 情報ブロックがあることを示す 007D 3 WORD 情報ブロックのサイズ(現行のNSF 1.0 では 00h にする事) 0080 n ---- 情報ブロック(オプション。このブロックがある場合は7Chのビット7をHにする。) ???? n ---- 再生プログラムとデータが続きます。 情報ブロックの構成: ━━━━━━━━━━━━ 0000 1 BYTE レコードのタイプ 0001 2 WORD レコードのサイズ 0003 1 BYTE レコードのトラック(0FFhはNSF全体の情報を示す。) 0004 n ---- レコードデータ レコードのタイプ --------------------------- 00h レコードの終了 この場合、レコードのサイズ、レコードのトラックは00hにする事。 つまり、00hが4[Byte]並ぶ事になる。 01h 曲名 02h 作曲者 03h 著作権者 例えば、トラック 0FFh で作曲者を指定し、 トラック 002h のみ個別に作曲者を指定した場合は、 トラック 002h 以外の作曲者は、トラック 0FFh に書かれた作曲者が適用され、 トラック 002h は、個別に指定された作曲者が適用される。 また、実装を検討されているレコードタイプは(IDは仮の番号)、 01h 曲名 (ASCII 若しくは UNICODE の文字列) 02h 作曲者 (ASCII 若しくは UNICODE の文字列) 03h 著作権者 (ASCII 若しくは UNICODE の文字列) 04h 抜き出し者 (ASCII 若しくは UNICODE の文字列) 05h 曲の長さ (秒、ミリ秒、NMIカウント?)  ※単位はまだ決まってないって事? 06h タイプ (効果音、曲、タイトル曲, 等など) 07h 補助データ (例えば、エントリーナンバー、何のカバーか。等) IRQへの対応 ━━━━━━━━━━━━ ヘッダーの007Chのbit 0がHの場合は、 APUのフレームIRQや、儕CM-IRQなどの、割り込み"IRQ"を使用可能です。 また、16bit IRQタイマー割り込みを使用できます。 IRQベクタの0FFFEhと0FFFFhはR/W可能です。 但し、IRQベクタを書いて設定した後は、F000h-FFFFhの領域のバンク切り替えをしてはならない。 ---------------------------------------- ※【訳者注】 実機再生の事を考えると、割り込みベクタ(0FFFEhと0FFFFh)は予め書いておくべきだと思う。 実機ではこのアドレスはROMであることと、あと、 このアドレスへの書き込みは、実機だとSUNSOFT 5bが受信しちゃうわけで。 ---------------------------------------- 提案されているタイマー割り込みデバイスの仕様は、 4018h R/W 16bitタイマーの下位8bit 4019h R/W 16bitタイマーの上位8bit 401Ah R/W 制御レジスタ bit 0 0:タイマー・オフ & リセット / 1:タイマー・オン bit 1-6 未使用 bit 7 IRQ 要求フラグ タイマーIRQは、タイマー設定値+1 [clock]間隔で発生する。 ---------------------------------------- ※【訳者注】 もちろん、実機にはこんなタイマー割り込みデバイスは実装されていません。 NSFでこのタイマー割り込みを使う場合は、NSF再生のカートリッジ側に、 タイマー割り込み回路が実装されている事が必要です。 ただし、実機用にタイマ割り込み回路を設計・開発する場合、 このNSF 2.0 の仕様どおりに作れるかどうかは未知です。 少なくとも、タイマー割り込みが要求された時、401Ahを読む事で、 タイマー割り込み回路に、IRQ処理したことを通知する必要がある気がします。 これは、回路上でIRQ信号(割り込み要求信号)を'H'に戻さないといけないためです。 そして、1回読み込むと、401Ahのbit 7は0にクリアされる仕様になると思います。 ---------------------------------------- IRQの使用例: -------------------------------------------------------------------------------- timervalue: .equ 01fffh ;desired # of cpu cycles minus 1 ;IRQタイマー割り込みのセットアップ starttimer: LDA #000h STA 0401ah ;タイマーデバイスのリセット LDA #irqvector STA 0ffffh ;IRQ割り込みベクタの設定(上位8bit) LDA #timervalue STA 04019h ;タイマー値の設定(上位8bit) LDA #0c0h STA 04017h ;frame IRQ オフ LDA 04015h ;儕CMのIRQ要求をリセット CLI ;IRQ有効 LDA #01h STA 0401ah ;タイマーオン RTS ;IRQタイマー割り込みのシャットダウン stoptimer: SEI ;IRQ無効 LDA #000h STA 0401ah ;タイマーオフ RTS ;IRQ割り込みルーチン irqvector: BIT 0401ah ;IRQタイマー割り込みかチェック BPL @L1 JSR timer ;bit7=1だったら、タイマー割り込みルーチンへ @L1: BIT 04015h ;APUのIRQかチェック BPL @L2 ;儕CM-IRQかチェック PHP ;フラグの一時保存 JSR dpcm ;bit7=1だったら、儕CM割り込みルーチンへ PLP ; @L2: BVC @L3 ;フレームIRQかチェック JSR frame ;bit6=1だったら、儕CM割り込みルーチン @L3 RTI ;IRQ割り込み終了 timer: <タイマー割り込みルーチン> RTS dpcm: <儕CM割り込みルーチン> RTS frame: <フレーム割り込みルーチン> RTS -------------------------------------------------------------------------------- 曲の初期化 ━━━━━━━━━━━━ ヘッダーの007Chのbit 1がHの場合は、『戻らない初期化ルーチン』です。 本来の割り込み(NMI, IRQ)を用いて再生を制御する為のフラグで"real NES"モードです。 この基本的な意味は、 ・初期化アドレス(ヘッダー000Ah)は、割り込みベクタの"RST"になり、 ・再生アドレス(ヘッダー000Ch)は、割り込みベクタの"NMI"になり、 ・IRQは0FFFEh〜0FFFFhにベクターを持ちます。 ---------------------------------------- ※【訳者注】 つまり、NSFプレイヤーは、NSFが読み込まれたときに、 NSFヘッダーに書かれた初期化アドレスと再生アドレスを、 割り込みベクタ"RST"と"NMI"にそれぞれ書かなければ(コピーしなければ)ならない。ってこと? IRQだけは、NSFヘッダーに書く領域が無いので、そのベクタ(0FFFEh〜0FFFFh)はRAMにすると。 ---------------------------------------- ---------------------------------------- ※【訳者注】 ヘッダーの007Chのbit 2がHの意味を推測すると、 これは、再生(NMI)ルーチンではなく、IRQタイマー割り込みでシーケンスを制御したい場合に、 再生(NMI)ルーチンを無効にする用途だと思う。 ----------------------------------------