---------------- Bankchange Howto ---------------- 今は#AUTO-BANKSWITCHを使えばいいので、このテキストは参考程度に。 http://pc5.2ch.net/test/read.cgi/dtm/1094914696/488 488 名前:名無しサンプリング@48kHz[sage] :04/11/23 22:19:42 ID:savbbxyd ff11_110v01.mmlを題材にSETBANKのやり方を書いてみます。 とりあえず、 ----------- #SETBANK A,3 ;(DPCMをたくさん使うときはSETBANK A,4) BCDEGHIJKLMNOPQRSTUVWXYZab NB ----------- とします。(これでほぼ1チャンネル1バンク割り当て) さらにファイルサイズを小さくするために nesasmのエラーが出なくなるまで先頭1文字ずつ削っていきます。 ----------- CDEGHIJKLMNOPQRSTUVWXYZab NB DEGHIJKLMNOPQRSTUVWXYZab NB : MNOPQRSTUVWXYZab NB ----------- 削っていくと、ここでbank overflowエラーが出るので、Lを復活させ、次の文字を削っていきます ----------- LMNOPQRSTUVWXYZab NB LNOPQRSTUVWXYZab NB LOPQRSTUVWXYZab NB : ----------- てのを繰り返すと LSa NB まで行きます。これでもOKですがさらに小さくするためには あとbank 1も空いているので ----------- #SETBANK A,1 #SETBANK L,3 Sa NB 489 名前:名無しサンプリング@48kHz[sage] :04/11/23 22:25:32 ID:savbbxyd pmck系のバンク切り替えの仕組みは 某吉さんのページ(http://www.emucamp.com/boukichi/)→過去配布物 の図を見てください。 SETBANKやNBコマンドが実際に正確なところ何をやってるのかは 出力ファイルのsongdata.hを見ながら色々試してみるとわかるのではないかと、、 http://pc5.2ch.net/test/read.cgi/dtm/1094914696/701 701 名前:名無しサンプリング@48kHz[sage] :04/12/26 19:42:14 ID:MQJCkV6u で、ff11_110v01.mmlを題材にSETBANKのやり方をまた書いてみます。 とりあえずSETBANK、NBを何も書かずにコンパイル。エラーが出ます。 #[3] ff11_110v01.h 198 00:A003 db $fd,$5e,$f4,$01,$f4,$08,$fd,$14 ;Trk A; ff11_110v01.mml: 140 Bank overflow, offset > $1FFF! このエラーの読み方ですが #[3] ff11_110v01.h 198 00:A003 (中略) ;Trk A; ff11_110v01.mml: 140    ↑バンク0で  ↑トラックAで↑このファイルの↑140行目 というわけでその手前にNBを入れます([ 〜 ]や|: 〜 :|の中にNBを書かないように注意) 139行目: AB r1r1r2. g4> 140行目: A NB ;←これ 141行目: AB l4[e2dcc16w16dc2 …ってのを繰り返します。 ところで、 bank 3にトラックデータを書き込むと VirtuaNSFで再生がおかしくなることがあります。 (発現条件も正確にはよくわかりません) NSFplugとかNotSo FatSoとかVirtuaNESだと大丈夫です。 http://pc8.2ch.net/test/read.cgi/dtm/1119956602/169 169 名前:名無しサンプリング@48kHz[sage] :2005/08/31(水) 23:12:03 ID:e184rErQ ここからが本題です。 Bank overflowとその対策について詳細に述べます。 まず基本知識として(pp)mckシステムの全体像を説明します。 (pp)mckは曲データを読み込み、演奏する(音源を操作する)プログラムです。 曲データはMMLでもMIDI(SMF)でもなくて専用の形式を用いています。 専用形式の曲データを人間が手で書くのは面倒なので、mck専用曲データは MMLテキストファイルから(pp)mckc.exeで変換して作成します。 変換した結果(effect.hとsongdata.h)を、(pp)mckの再生ルーチンのソースコードもろとも nesasmでコンパイルします。するとファミコンorエミュレータで実行可能なデータ (機械語バイナリなROMイメージ)になります。 次に、nesasmの仕様について説明します。 nesasmには「バンク」という概念があります。これは、nesasmが出力するファイルの 出力バイナリオフセット位置を8KB(8192バイト)ずつ区切ったものです。 bank 0は(iNESヘッダを除いた)0x0000〜0x1FFFを表し、bank 1は0x2000〜0x3FFF… となっています。nesasmのbankの概念は、あくまでも出力バイナリのオフセット位置であり、 どのbankが何を意味するかはまた別の問題です。 ppmckの場合は各bankを次のように使用しています。 ■bank 0  必ず使用される。  ppmckプログラム本体、@v・EPなどエフェクト用数字配列、曲データがここに置かれる。  nsfバイナリオフセット位置0x0000〜0x1FFFに対応する。  NES CPUアドレスの0x8000-0x9FFFに対応する。 170 名前:名無しサンプリング@48kHz[sage] :2005/08/31(水) 23:13:06 ID:e184rErQ ■bank 1  通常は未使用。  #SETBANK、NBを指定することにより、曲データをここに置くこともできる。  nsfバイナリオフセット位置0x2000〜0x2FFFに対応する。  NES CPUアドレスの0xA000-0xBFFFに対応する。 ■bank 2  通常は未使用。  DMCを使用する場合、ここにDMCデータが置かれる。  bank 2の全てがDMCデータで埋まることもある。  bankに空きがあれば、#SETBANK、NBを指定することにより、曲データをここに置くこともできる。  nsfバイナリオフセット位置0x3000〜0x3FFFに対応する。  NES CPUアドレスの0xC000-0xDFFFに対応する。 ■bank 3  通常は未使用。  DMCデータが8KBを超える場合、ここにもDMCデータが置かれる。  bank 3の全てがDMCデータで埋まることもある。  bankに空きがあれば、#SETBANK、NBを指定することにより、曲データをここに置くこともできる。  nsfバイナリオフセット位置0x4000〜0x4FFFに対応する。  NES CPUアドレスの0xE000-0xFFFFに対応する。 ■bank 4以降  通常は未使用。  #SETBANK、NBを指定することにより、曲データをここに置くこともできる。  nsfバイナリオフセット位置はbankに対応する位置に対応する。  NES CPUアドレスの0xA000-0xBFFFに対応する。  * DMCデータが16KBを超える場合、ここにもDMCデータが置かれる。  * この場合はNES CPUアドレスの0xC000-0xDFFF, 0xE000-0xFFFFどちらかに対応する。  #NO-BANKSWITCHを使用する場合、bank 4以降は使用できない。  bank 4以降を使用する場合、現状のTNS-HFC1-Eでは再生できない。 171 名前:名無しサンプリング@48kHz[sage] :2005/08/31(水) 23:14:04 ID:e184rErQ 各バンクは8KB以内に収めなければなりません。 8KB以内に収まっていない場合、 pass 1 #[3] tr01.h 713 00:A002 db $fc,$0b,$02,$0c,$fc,$0b,$00,$0c ;Trk E; tr01.mml: 39 Bank overflow, offset > $1FFF!  ←これ # 1 error(s) のようなエラーが出ます。これが「Bank overflowエラー」です。 Bank overflowエラーメッセージには読み方があります。 #[3] tr01.h ←このファイルの 713 00:A002 db (中略) ;Trk E; tr01.mml: 39    ↑バンク0で    ↑トラックEで↑もとはこのファイルの↑39行目 となっています。 この場合、曲データの一部を他のバンクに移動させることによりbank overflowを 回避することができます。Eトラックの39行目でbank overflowしたということなので、 (少し余裕を持って)Eトラックの最初、つまり12行目を E o0 NB と変更します。 これで、Eトラックの13行目以降、および(このMMLにはありませんが)Fトラック以降は bank 1に入ります。Eトラックの一部がbank 1に移動したぶんbank 0に余裕ができたので、 bank 0は8KB以内に無事収まり、さらに曲データを追加することができます。 NBコマンド、SETBANKコマンドの詳細についてはWikiを参照してください。 http://akane.fam.cx/mck/index.php?MML%A5%EA%A5%D5%A5%A1%A5%EC%A5%F3%A5%B9 172 名前:名無しサンプリング@48kHz[sage] :2005/08/31(水) 23:15:04 ID:e184rErQ さて、 #SETBANK A,3 BCDE NB としておけば、各トラックにひとつずつバンクが割り当てられることになるので、 Bank overflowは発生しにくくなります。nsf作成中はこの状態にしておくと良いでしょう。 しかし、この方法は2つ問題があります。 1)bank 4以降を使用しているためTNS-HFC1-Eで再生できない 2)ファイルサイズが無駄に大きい グラフィック表示できるバイナリエディタで見るとわかるのですが、 ファイルサイズが大きくても未使用領域が多く、かなり「スカスカ」です。 もっと無駄のないバンク配置をしたくなります。 さきほど説明したように、Bank overflowエラーが発生したときは そのエラーメッセージを読むことで、曲データ中のどこでbank overflowしたのか 知ることができます。このことを利用します。 NSF作成中はさきほどの方法でバンク切り替えしておきます。 NSFが完成したならば、まずSETBANK、NBを全て消去してコンパイルします。当然エラーが出ます。 エラーメッセージを読み、たとえばBトラック104行目でoverflowしたのならば、104行目に B NB @1 q6 o5 v6 l16[[ec]4 fcec [ec]4fe]2 のようにNBを追加します([ 〜 ]や|: 〜 :|の中にNBを書かないように注意)。 もう一度コンパイルし、まだBank overflowするならばさらにNBを追加します。 これをエラーが出なくなるまで繰り返します。 これならばBank overflowする直前にバンクを変えているので ファイルサイズは小さくなります。bank 3までに収まればTNS-HFC1-Eで再生できます。 173 名前:名無しサンプリング@48kHz[sage] :2005/08/31(水) 23:16:03 ID:e184rErQ さて、以下では曲データサイズそのものを小さくする方法について説明します。 (pp)mckの曲データの表現形式はかなり効率が悪いので、すぐにデータが膨らみます。 特に、[ ]コマンドを使用したリピートは基本的にベタ展開であり、データが巨大になりがちです。 たとえば>>159さんのMMLからの抜粋ですが >D l8 q1 [rfrfrfrf]12 たったこれだけで288バイトぐらい消費しています。 基本的にはベタ展開と書きましたが、テンポ指定によっては繰り返されるデータが テンポ調整のため少しずつ異なることもあります。 さて、リピートのコマンドはもうひとつ|: :|コマンドがあります。これはベタ展開ではないので データサイズを節約できます。 ここで実験ですが、さっきの行を D l8 q1 |:rfrfrfrf:|12 に変更してみます。するとノイズチャンネルがしだいにずれていきます。 これは、リピート内のrfrfrfrf(全音符1個ぶん)のフレーム数計算結果がt156において 半端な値になるからです。 BPM156 = 4分音符156個/1min = 全音符39個 / 60sec = 全音符39個 / 60*60フレーム = 39/3600 (全音符/フレーム) よって全音符1個は3600/39 = 92.3...フレームです。[ ]リピートを使用する場合、 ppmckcは繰り返しごとにフレーム数を少しずつ変えて端数のつじつまをわせます。 しかし|: :|を使用した場合は整数値に丸めるため他のトラックとのテンポずれが生じます。 174 名前:名無しサンプリング@48kHz[sage] :2005/08/31(水) 23:17:13 ID:e184rErQ つまり、 ・ [ ]リピートを使用するとデータが増大する ・ |: :|リピートを使用するとテンポがずれる というジレンマが発生します。そこでテンポを「きりのいい」値に変更することを考えます。 テンポ設定にはtコマンドのほかに、@tコマンドがあります。 http://takamatsu.cool.ne.jp/dutycycle/at_t_tempo.html を見ると、@t4,23とするとBPM156.52になることがわかります。 そこで t156 を @t4,23 に置き換えます。こうすると4分音符1個は23フレームになります。 さきほどの|: :|の中身は全音符1個分だったので23*4=92フレームになります。 端数がなくなるところがポイントです。 @t4,xxでテンポを指定した場合、|: :|の中身の長さが4分音符の整数倍であれば |: :|を使用してもテンポずれを起こすことはありません。 これで|: :|を使ってもテンポずれが起きなくなったので、 MML中の全ての[ ]を|: :|に置き換えればデータサイズの節約になります。 ただし|: :|の中に|: :|を置く(ネストする)ことはできないので、 その場合は内側か外側のどちらかを[ ]のままにしておきます。 ----- レスは以上です。