このページでは、S98ファイル作成方法の説明をしています。
この手順書は、筆者が実際にループ化を行うときに実施する方法を記したものです。
もっとも原始的な方法でループ化を行う手順を記していますが、現在ではループ化を手軽に行うことができるツールも存在しています。
基本的にそちらを利用することを推奨しますが、バイナリエディタを見ながらログを加工するという方法は、ADPCMデータを埋め込む等の処置を行うときに必要なため、覚えておいて損しないと思われます。
また、サウンドドライバによっては、ここで説明している手順、および目印を見つけることができない場合も存在します。
その場合は、極めて些細な違いを見分けるか、ログを削ってループ化しやすい位置に終端を合わせる、という手段を取るケースもあります。
バイナリエディタでログを加工する手段は、いざというときに役に立ちます。(M88のメモリを弄ぶとか、スナップショットのデータを改竄してパラメータを最強にする、といった応用もできますから。
s98ログは、Mamiya氏が提唱した Ver1 , Ver2 と、RuRuRu氏が独自拡張を行った Ver3 が存在します。
M88やNeko Project II などが出力するログは、Ver1 または Ver2 の形式となっています。
Ver3 形式を出力するエミュレータおよび演奏プラグインは、RuRuRu氏のサイトで配布されています。
この説明書では、とりあえず Ver1 形式のログについて説明します。
Mamiya氏の作成した s98spec1.txt は、以下のように設定されています。
[S98 V1 HEADER FORMAT]
0000 3BYTE | MAGIC 'S98' |
0003 1BYTE | FORMAT VERSION '1' or '0' |
0004 DWORD(LE) | TIMER INFO sync time(ms) If value is 0, default time is 10ms. |
0008 DWORD(LE) | RESERVE FOR TIMER INFO 2 |
000C DWORD(LE) | COMPRESSING 'Inflate' size in byte.If value is 0, notcompressed. |
0010 DWORD(LE) | FILE OFFSET TO SONG NAME If value is 0, no title exist. |
0014 DWORD(LE) | FILE OFFSET TO DUMP DATA |
0018 DWORD(LE) | FILE OFFSET TO LOOP POINT DUMP DATA |
001C-003F | HEADER RESERVE |
[DUMP DATA FORMAT]
00 aa dd | OPNA(master) |
01 aa dd | OPNA(slave) |
FF | 1SYNC |
FE vv | nSYNC |
FD | END/LOOP |
とりあえず、ループ化作業とかで重要となるヘッダの一部分だけ抜粋して説明します。
0010 : 曲名情報が記載されているアドレスを指定する。
0014 : 曲データの始まりアドレスを指定する。
0018 : ループして戻ってくるアドレスを指定する。
デフォルトでは、0018 からの4バイトには 00 が入っています。
そのため、ループせずに演奏が終わるようになっています。
ループして戻ってくる地点はここだよ、とポイントを指定してあげることで、繰り返し演奏を行ってくれるようになります。
0014 は、ここから始めてね、というポイントを指定します。
デフォルトではログの開始位置である 80 00 00 00 が入っています。
冒頭に無音時間がある場合、この位置を曲が始まるとこに再設定してあげることで、無音部分を無視して演奏を始めてくれます。
滅多にいじることはありませんが、無音化ツールでも無音が取れない場合などに弄びます。
0010 は、デフォルトで 40 00 00 00 が入っています。曲名情報を 40h から書き始めるのは、ここで設定されているからです。
64文字でも足りない!という場合は、この数値を 20 00 とかにして、20h から曲名を書き始めることができます。
20hからだと、96文字まで使えるようになるので安心して長い曲名を書くことが出来ます。
サンプルとして日本テレネットの「テレネット・ミュージックボックス」オープニングBGM「POP KISS」をループ化する手順を示します。
ログ作成環境は、M88エミュレータ+SlogFXの構成となっています。
#ref(): File not found: "0001.png" at page "G.I.M.I.C/S98フォーマット ループ化作業手順"
#ref(): File not found: "0002.png" at page "G.I.M.I.C/S98フォーマット ループ化作業手順"
#ref(): File not found: "0003.png" at page "G.I.M.I.C/S98フォーマット ループ化作業手順"
#ref(): File not found: "0004.png" at page "G.I.M.I.C/S98フォーマット ループ化作業手順"
#ref(): File not found: "0006.png" at page "G.I.M.I.C/S98フォーマット ループ化作業手順"
ログが正しく取られていたら、バイナリエディタに読み込ませます。
#ref(): File not found: "0005.png" at page "G.I.M.I.C/S98フォーマット ループ化作業手順"
s98ファイルは、00000000h ~ 0000007Fh までがヘッダ領域となっています。
00000080h以降がサウンドログのデータ部分となっています。
ループ化をするためには、以下のポイントを探す必要があります。
まずは、ループする地点(ここまで来たら戻りアドレスに戻って演奏を続ける)を探します。
ループ直後にログの録音を終わらせているなら、ちょっと戻るだけでループ地点に到達できますが、録音を続けていると、結構戻らなくてはならないので見切るのが大変です。
このあたりは、何度も曲を聴いてタイミングを計る必要があります。
A-B-A-B-C構成の曲だと、ループしたと思って録音を終わらせたらCパートが始まってやり直し、なんてことがよくあります。
市販サントラではA-B-A-Bで終わっていた曲が、実はA-B-A-B-Cの構成になっていた、というケースが稀にあります。
マイクロキャビンのXakでは、終盤のシューティングシーンBGMがこのケースになります。
ソーサリアン基本シナリオの「天の神々たち」で流れるBGMも、サントラでは途中で終わっています。
CDやテープの収録時間による弊害だと思いますが、買ったほうとしては納得できませんよね。
ログを作成していると、このような事実を知ることが稀にあります。
データの終端から戻っていくと、あきらかに他のデータ部分と違うパターンがあります。
#ref(): File not found: "0007.png" at page "G.I.M.I.C/S98フォーマット ループ化作業手順"
このパターン部分は、音色定義などで発生します。
曲を戻すときに音色もリセットするドライバならこのパターンが出ますが、音色が変化しない曲では、こういった「明らかに違うパターン」が無いので、そういったデータは目印候補を探すのが大変です。
後述しますが、そんなデータでも有効な目印探しを簡単にする手段はあります。
とりあえず、目印にしたポイント以降で、最初にでてくる FF コードを探します。
#ref(): File not found: "0008.png" at page "G.I.M.I.C/S98フォーマット ループ化作業手順"
Ffコードは、1ウェイト(譜面でいうところの小節線のようなもの)を表しているので、ここで各パートのデータが区切られています。
先ほど見つけたFFコードから、データ終わりを示すFDの手前まで、きれいさっぱり削除してしまいます。
#ref(): File not found: "0009.png" at page "G.I.M.I.C/S98フォーマット ループ化作業手順"
この部分はループした後に演奏される「ダブリデータ」となるので、この部分を残しておくと位置調整が難しくなります。(データもそのぶん大きくなります)
このように、綺麗さっぱり消してしまいましょう。
不安な場合は、s98ファイルのコピー(バックアップ)を取っておけば、失敗してもそちらのファイルをコピーすればよいので、安心して作業できます。
#ref(): File not found: "0010.png" at page "G.I.M.I.C/S98フォーマット ループ化作業手順"
終端の目印と加工が終わったら、戻ってくるポイントを探します。
データの頭から見ていくと、ちょっと下がったところで目印と同じような部分を見つけることができました。
そこからFFコードを探し、そこをループポイントと仮設定します。
#ref(): File not found: "0011.png" at page "G.I.M.I.C/S98フォーマット ループ化作業手順"
アドレス 00000560h がポイントなので、これを 00 00 05 60 という4つの2桁文字列に分離します。
記述するときは、下の桁から書いていく必要があります。
そのため、ヘッダには 60 05 00 00 と入れることになります。
ループ地点を指定する部分は、 00000018h からの4バイトとなっていますので、この部分に 60 05 00 00 と記載し、とりあえず上書き保存(または別名で保存)します。
#ref(): File not found: "0012.png" at page "G.I.M.I.C/S98フォーマット ループ化作業手順"
ループ化を行ったファイルを演奏させてみます。
先ほどは、1:17 だった演奏時間が 2:31 に増加しています。
#ref(): File not found: "0015.png" at page "G.I.M.I.C/S98フォーマット ループ化作業手順"
これでループする部分が違和感なく繋がればいいのですが、あいにく POP KISS という曲は冒頭にイントロが入っています。
そのため、ループ地点に差し掛かると、このイントロ部分に戻ってきて正しく繋がってくれません。
これではダメなので、イントロ後のスムーズに繋がるポイントを探さなくてはなりません。
先ほどの地点から更に続きを見ていくと、今度は 00001780h あたりで、音色定義を行っている部分を見つけることができます。
ここがイントロ後の音楽演奏部分であることが想像できます。
#ref(): File not found: "0013.png" at page "G.I.M.I.C/S98フォーマット ループ化作業手順"
該当地点付近の FF を探し、そこをループ戻り地点として登録し直します。
再度、演奏させてみます。違和感なく曲が繋がっていれば成功です。
#ref(): File not found: "0014.png" at page "G.I.M.I.C/S98フォーマット ループ化作業手順"
なんか微妙に違和感が・・・、という場合は、前後の FF にポイントを移動するなどして、ポイントの微調整をおこなっていけば、違和感無く繋がるポイントを見つけることができると思います。
きっちりしたところで切ると、違和感ある繋がり方にしかならない場合もありますので、途中で行った終端までのデータ削除をやらずに、ポイントを指定するとスムーズに繋がる場合も時にはありますので、ケースバイケースで対応する必要があったりします。
そのときは泣きながらバイナリエディタとにらめっこするか、ログを取り直して目印になるポイントでループ化させる、という方法を使うと良いでしょう。
普通にスクロールさせて見ていくのが面倒な場合は、バイナリエディタの検索を使いましょう。
これは、戻り地点で音色定義が存在しないデータに対しても使える小技です。
検索する文字列は、バイナリエディタ左側の16進データです。
#ref(): File not found: "0021.png" at page "G.I.M.I.C/S98フォーマット ループ化作業手順"
音色定義部の目印(前記POP KISSループ化の場合、下線が引いてあるデータ)を検索データとして使用し、データ末端から 前検索していき、ポイントを探し出します。
データ末尾から頭まで戻していくと、候補間ジャンプ幅にパターンがあることが分かります。
その移動量から、ループして戻ってくる地点を特定することができます。
たとえばジャンプ移動量が、
頭__________________________________終
A_B__C_D_______E____F_G__H_I_______J
このような幅であれば、JからEに戻れば丁度いい地点になるのではないか、と予測することができます。
このように、些細なパターンを見つけることが、ループ地点を特定するのに必要なキーとなっています。(このあたりは慣れの問題ですけどね…。)
検索文字列が秀逸だと、
頭 終
■ ■ ■
このように、曲頭だけが反応します。この場合は何も考えずに付近のFFを選択するだけで済むので、非常にループ化がしやすくなります。
音色定義情報がでてきたのち、一定間隔ずーっと同じような文字列が続く形式のログがあります。
#ref(): File not found: "0020.png" at page "G.I.M.I.C/S98フォーマット ループ化作業手順"
サウンドドライバの制御方法が定期的にデータの塊を放り投げるタイプだと、こういったログになります。
この手のログは 4MHz で動作するソフトに多いのですが、8MHz 動作のソフトでも稀に使っています。
このタイプは判別ポイントの目視が大変です。(移動量がPOP KISS系ログの数倍になります)
動作させる周波数によって、ログのサイズが変動します。
テンポが崩れない程度でエミュレータの動作クロックを抑えていくと、ファイルサイズの小さいログを作ることができます。
たとえば、システムサコムのChattyでは、4MHz クロック推奨のところを 2MHz クロックで動かしてログを作りました。
日本ファルコムの Star Trader は、動作クロックを 1MHz にしても普通に演奏してました。
これは効果音が入らないようにするため落としていたのですが、こんなクロックでも普通に演奏するドライバを作るとは・・・。
よほど優秀なプログラマが在籍していたのでしょうね。
・・・話がそれてしまいました。すいません。
ADPCMデータも、普通のログ取りと同じ方法で取得することが出来ます。
The Scheme のスペシャルBGMも、ADPCMデータを曲の頭に挿入することで、ADPCMを駆使したゴージャスな音楽を堪能することが出来ます。
ADPCMデータを読んでいるときは、ディスクアクセスに特徴がある(データを読んでメモリに展開、またデータを読んで展開・・・)上、大抵のソフトでは「PCMデータ読み込み中」といったメッセージが画面に出るので、いつ読み込んでいるのか把握することができます。
The Schemeの場合、データを読むのに8秒くらいかかっています。
一旦メモリに展開してしまえば、プラグインが完全に終了するまで残っているので、最初にADPCMデータ(無音)を流してもらってから、普通に作ったログを演奏してもらう、という方法でも堪能することができます。
しかし、せっかくデータを取れるのだから、それぞれの曲頭でADPCMデータを読み込ませ、単独で堪能できるようにしたいのが人情です。
冒頭に8秒の無音時間が付加されるのも嫌なので、ADPCMデータを読んでいるときのログから、ウェイトをなくす必要があります。
手作業で行うこともできますが、ふくい.氏により、無音部分のウェイトをカットするツールが作成されておりますので、このツールを使ってウェイトをなくし、瞬時にADPCM転送を終わらせるように加工します。
このデータを曲の頭にもってきても、8秒たたないと演奏が始まりません。
それじゃあ、やっぱり嫌ですよね。一瞬でPCM転送してほしいです。
そんなときは、冒頭無音時間カットツールを使いましょう!
冒頭無音時間排除ツールをダウンロードします。
#ref(): File not found: "0023.png" at page "G.I.M.I.C/S98フォーマット ループ化作業手順"
適当なフォルダに解凍し、同じところにADPCMログをコピーします。
コピーしたら、おもむろに go.bat をダブルクリックして起動します。
そうすると、 NEW と NEWLOG というフォルダが作成され、無音時間を排除したデータが NEW フォルダに作成されます。
これで瞬間的にADPCMデータを転送できるログが完成しました。
RuRuRu氏によって、ADPCMデータ読み込み中にBGMが演奏されていても分離してファイルに切り出してくれるツールが作成されました。
従来のPCMデータは、単に無音化して瞬時転送を行うようにしただけで、通常の音色設定その他のデータが残されています。
そのため、こちらの切り出しツールを作成したほうが純粋なADPCMデータを作成することができます。
使用方法は、ADPCMデータを読み込んでいるときのs98ファイルを s98sep.exe にドロップします。ただこれだけ。
#ref(): File not found: "0030.png" at page "G.I.M.I.C/S98フォーマット ループ化作業手順"
そうすると、ADPCMデータとそうでないデータが分離されます。
#ref(): File not found: "0031.png" at page "G.I.M.I.C/S98フォーマット ループ化作業手順"
素晴らしい簡単さで利用できます。
瞬時にADPCMデータを転送するログは作れましたが、このままではヘッダ部分やデータ末尾のログ終了を示す FD コードなど、不要なデータがついています。
このまま曲が演奏されるデータに割り込み挿入すると、破損データと扱われたり、ADPCM転送直後の FD を読み、終了してしまう・・・。
などなど、不具合が出て正しく演奏されません。
そのため、ゴミ部分を削除する必要があります。
1. 00000000h ~ 0000007Fh のヘッダ領域は不要です。さくっと削除してしまいましょう。
#ref(): File not found: "0024.png" at page "G.I.M.I.C/S98フォーマット ループ化作業手順"
2. データ末尾の FD コードも不要なので、これも削除します。
ヘッダ領域と末尾のFDを削除したことで、 瞬時ADPCM転送部分のログだけが残ります。
これを『 ADPCM.bin 』といった適当な名前で保存します。
同一ソフト内なら、違うADPC使用曲にも流用することができます。(よほど凝ったものでないかぎりは…)
これでADPCMデータの準備は出来ました。
純粋なADPCMデータだけが切り分けられているので、取り出されたADPCMファイルは別に何も加工する必要はありません。
そのまま 80h に割り込ませましょう。
#ref(): File not found: "0032.png" at page "G.I.M.I.C/S98フォーマット ループ化作業手順"
ヘッダ部と終端の FD コードを排除したデータを用意したら、ADPCMを使用している曲のログに挿入します。
ADPCMデータは、演奏が始まる前に読み込ませる必要がありますので、ヘッダの直後 00000080h に割り込み挿入させます。
Schemeの場合、約 311KB のADPCMデータを挿入します。
#ref(): File not found: "0025.png" at page "G.I.M.I.C/S98フォーマット ループ化作業手順"
挿入したらセーブして、演奏させてみましょう。
ADPCM部分つきで演奏されていれば成功です。
#ref(): File not found: "0026.png" at page "G.I.M.I.C/S98フォーマット ループ化作業手順"
ここで注意すべき点は、既にループ化処理を行っていた場合、ループポイントの設定や、開始位置の設定をやり直す必要がある、ということです。
忘れずに再設定しておきましょう。
ログの加工を忘れてると、破損データとして認知されてしまったり、ADPCMデータを転送した直後に演奏を終えてしまうという不具合が出ます。
ログの加工は忘れずに、かつ慎重に行いましょう。
Q1.曲が最期まで演奏されないうちにキャンセルされちゃうよ!
A1.
デモやビジュアルシーン(懐かしい言葉だ)で、曲が演奏されている間にCG等を読み込む場合、CG読み込みが入る前にディスクイメージを抜いてしまいましょう。
そうすると、データを読む時間を延長させることができ、曲を最期まで演奏できるようになります。
途中で読み込まない場合は、処理をなるべく遅くさせるため動作クロックを下げてしまうという手もあります。
悪あがきなので、ちょっと長めにログを取れるという程度ですけど。
最終手段は、ディスクイメージ自体を書き換えて、最後まで取れない曲が流れるシーンを変更してしまうという手段もありますが、これは高度な知識が必要です。
(筆者はそこまでテクを持ってないので、解析できません。)
Q2.効果音が入っちゃうよ!
A2.
華麗に避けてください(笑)
私の作ったStarTrader は、動作クロックを 1MHz にして、ひたすら避けるプレイで作成しました。Xakも同様に避けまくりです。
動作クロックを落とせば、アクションゲームもだいぶ楽になります。
何個もログを作成して、効果音が入っていない部分を切り貼りするという手段もあります。手作業で判別しまくる必要があるので、気合と根性が必要ですが。
動作中にメモリをいじくって効果音を排除するという、高等テクニックもあるようですが、私はそこまでできません。
(教えてもらったり、適当にいじったら偶然なったという感じ)
CPUのレジスタとかコード分かる人は見切れるんだろうなあ。尊敬。
Q3.クソ長い曲も普通に聞いてなきゃダメなの?
A3.
旧版のsndlog.m88 では、エミュレータを高速動作させることで、倍速ダビングのようにログを高速吐出しすることができていました。
新版のslogFXでは試していないので、できるかどうかわかりませんが、たぶんできるんじゃないかなあ。
しかし、途中でクロックが変動するため、サウンドドライバによってはとんでもない肥大化ログになるだけで意味がなかったりします。
また、中身を見たらグジャグジャだったり、2分くらいの曲なのに43分とか判定されたり、テンポヨレしたりと不具合が出るリスクも高くなります。
個人的にはちゃんと曲を聴きながらログを作成して欲しいです。ダメ?
Q4.曲が始まるまでに無音時間があるよ!
A4.
ADPCMデータ作成で紹介した、無音時間をカットするツールを使いましょう。簡単手軽に冒頭の無音部分を殺ぎ落とせるので嬉しいです。
ログを見て判断できる場合は、00000080hからデータを舐めていって、音色定義コードが出てくる少し前までをバッサリ削除することでも無音部分を削除できます。
ヘッダの開始アドレスを設定する部分を書き換える、という手段もあります。
開始アドレスを指定している場所は、ヘッダの 00000014h から4バイトです。ループ化の設定同様、下の桁から記述してください。
Q5.なんか別フォーマットからS98への変換ができるみたいだけど?
A5.
RururuさんがVGM、X1FなどのフォーマットをS98に変換するツールを出されています。
ただ、変換してもデバイス番号が違うのでそのままでは鳴りません。
無理やり鳴らすのであれば、
・s98cv でVGMやX1FをS98化
・s98dmp でダンプファイルをテキスト化
・テキスト化したダンプのデバイス番号を変更
・変更したダンプを80hからバイナリで突っ込む
・既存のS98v3ヘッダを00hから書きこむ
こんな感じでデバイス偽装したS98をつくることで鳴らせるかもしれません。
ただし正規ログではないのでG.I.M.I.C.で正常演奏できないと思います。
2011-01-24 | QAの5を追記。 |
2011-01-23 | Wiki向けに多少文言を変更して記載。 |
2005-11-05 | その昔 AGMM/ESAF で公開していたループ手順のPDF化 |