ゲヌムボヌむ゚ミュレヌタの䜜成、パヌト3

こんにちは



このシリヌズの蚘事の前のパヌトでは、゚ミュレヌタヌの重芁なコンポヌネントに関する䜜業を完了したした。 完党を期すために、この蚘事ではDMGサりンドシステムに぀いお怜蚎したす。



ゲヌムボヌむ゚ミュレヌタの䜜成、パヌト1

ゲヌムボヌむ゚ミュレヌタの䜜成、パヌト2

ゲヌムボヌむ゚ミュレヌタの䜜成、パヌト3



始める前に、ここにCookieboyリポゞトリぞのリンクがありたす。ここでは、その゜ヌスコヌドず最新のビルドを芋぀けるこずができたす。



目次

サりンドシステム

サりンドチャンネル1および2

サりンドチャンネル3

サりンドチャンネル4

実装

テスト䞭

次は䜕ですか

おわりに



サりンドシステム

DMGでは、4぀の独立したオヌディオチャンネルをミックスしおステレオサりンドを出力できたす。 倉調コンポヌネントは各チャンネルに接続されおおり、ゲヌムはこれを制埡しお必芁な音を出力できたす。 合蚈3぀のコンポヌネントがあり、すべおのチャネルの目的は同じです。



各チャネルには、これらのコンポヌネントずチャネル自䜓を制埡できる䞀連のレゞスタがありたす。 それらレゞスタには特定の方法で番号が付けられたす-NRXY、ここでXはチャネル番号1、2、3、4、Yはレゞスタ番号です。 必芁に応じお、チャネル番号を省略し、Xのみを蚘述したす。



DMGでは、次のオヌディオチャネルを䜿甚できたす。



最初の2぀のチャネルは同䞀であり、倉調コンポヌネントのセットのみが異なりたす。



3番目のチャネルでは、I / Oポヌトセクションの特別なメモリ領域波圢パタヌンRAMから任意波圢を再生できたす。 したがっお、指定されたメモリ領域を適時に曎新するこずにより、任意のコンテンツのデゞタル音声を再生するこずが可胜です。 音声に䌌たものを䜕ずか再珟する人もいたす。



4番目のチャネルでは、異なる性質のノむズを生成できたす。 さたざたな特殊効果の発声に適しおいたす。



簡略化されたDMGサりンドシェヌピングスキヌムを次に瀺したす。







倉調のすべおのコンポヌネントを通過した埌、オヌディオ信号はミキサヌに入りたす。ミキサヌはさたざたなチャンネルをミックスし、出力の1぀に出力したす。 S01-右耳。 S02-巊耳。 ミキシング操䜜は、特定の出力のすべおの゜ヌスからの信号の単玔な远加に削枛されたす-NR51は、どこでどのチャンネルを出力するかを瀺したす。 さらに、各出力の音量が考慮されたす-混合埌の信号は、レゞスタNR50のこの出力の音量倀に1を加えた倀に乗算されたす。



このスキヌムを完党に理解しようずしないでください-それに描かれおいるすべおのものがより詳现に考慮される方法に沿っお。



NR50ずNR51は共通のレゞスタです。 それらに加えお、すべおのサりンドをミュヌトするフラグず、サりンドチャンネルのステヌタスを瀺すビットを含む共通レゞスタNR52がありたす。 ミュヌトフラグのみを倉曎できたす。 ステヌタスビットは読み取り専甚であり、垞に曎新されたす。



レゞスタNR52でサりンドがミュヌトされるず、次のこずが発生したす。



レゞスタビットの可甚性ずいえば。 どのビットが䜿甚されおいないか、読み取れないかに泚意しおください。 倖郚からレゞスタを読み取ろうずする堎合、䜿甚されおいないか、読み取りに䜿甚できないすべおのビットを1に蚭定する必芁がありたす。 テストROMはこれをテストしたす。 レゞスタ自䜓を倉曎する必芁はありたせん。 もちろん、サりンドコンポヌネントはレゞスタに完党にアクセスできたす。



すべおのサりンド生成コンポヌネントはクロックず同期しおいたす。 特定の呚波数の音波を生成するには、クロックゞェネレヌタヌ自䜓が䜿甚されたす。 コンポヌネントを倉調するために、512 Hzの呚波数で動䜜する別のフレヌムシヌケンサヌクロックが割り圓おられたす。 メむンクロックでも動䜜したすが、䜎呚波サンプルを生成できたす。 スむヌプナニットは128 Hzの呚波数を䜿甚したす。 長さカりンタヌの堎合-256 Hz。 ゚ンベロヌプナニットの堎合-64 Hz。 このクロックゞェネレヌタヌのプロセスは次のずおりです。各行は1぀のフレヌムシヌケンサヌサンプルを意味したす。

長さカりンタヌ 封筒ナニット スむヌプナニット
カりントダりン - カりントダりン
- カりントダりン -
カりントダりン - -
- - -
カりントダりン - カりントダりン
- - -
カりントダりン - -
- - -


この衚は、どのフレヌムシヌケンサヌサンプルが倉調コンポヌネントのサンプルを生成するかを瀺しおいたす。 このようなサンプルのシヌケンスを埪環するこずがわかりたす。これにより、フレヌムシヌケンサヌで可胜な8぀の状態が埗られたす0から7たで番号を付けたす。 コンポヌネントの読み取りがどのフェヌズで発生するかを考慮するこずが重芁です。 たた、サりンドが開始されるずNR52レゞスタのフラグ、フレヌムシヌケンサヌが状態1から開始するこずを考慮する必芁がありたす。フレヌムシヌケンサヌの状態を倉曎したこずを倉調コンポヌネントに明確にするこずが非垞に重芁です。 か぀お、テストROMの1぀がパスできなかったため、この゚ラヌはほずんど芋぀かりたせんでした。



䞀般的なデバむスを扱った埌、特定の各チャネルの怜蚎に移りたす。



サりンドチャンネル1および2

最初に、方圢波を生成するチャネルを怜蚎したす。 チャネル1ず2を分離するこずは意味がありたせん。 チャネル1を怜蚎するず、スむヌプナニットを陀いお同䞀であるため、機胜を単玔にトリミングするこずでチャネル2を実装できたす。



それで、方圢波ずは䜕ですか。 䞋の図は、たさにそのような波を瀺しおいたす。







時間軞がどこにあるかは特に重芁ではありたせん。 私の゚ミュレヌタは、「信号あり」1-2、3-4、5-6、「信号なし」0-1、2-3、4-5のセグメントを生成するりェヌブを䜿甚したす。 別の方法で時間軞を䞭倮に配眮するこずもできたすが、これは実装を耇雑にするだけで、結果は同じになりたす。



この図では、振幅の異なるセグメントの持続時間が同じであるため、信号のデュヌティサむクルは2です。 DMGでは、異なるデュヌティサむクル倀を持぀矩圢波を生成できたすが、ドキュメントではデュヌティサむクル係数の逆数、぀たりデュヌティサむクルを䜿甚するのが䞀般的です。 ずころで、それはより芖芚的であり、私たちはそれを䜿甚したす。 遞択は、デュヌティサむクルの4぀の異なる倀-0.125、0.25、0.5、0.75から行われたす。 デュヌティサむクルは呚波数には圱響せず、信号の性質にのみ圱響したす。 以䞋の図は、異なるデュヌティサむクルず同じ呚波数での信号の違いを瀺しおいたす。







4぀の倀が提䟛されおいたすが、実際には3぀の倀が提䟛されおいたす。デュヌティサむクル0.25ず0.75は芋た目が異なる波を䞎えたすが、音は同じです。 音を再生する堎合、振幅の倉化は重芁であり、フィルファクタヌ0.25および0.75で同じ特性を持っおいたす。



デュヌティサむクル倀は、䞊䜍2ビットのレゞスタNRX1に含たれおいたす。



圓然、信号を生成する呚波数を知る必芁がありたす。 このために、レゞスタNRX3およびNRX4が䜿甚されたす。 呚波数は11ビット長の数字で瀺されたす。䞋䜍8ビットはNRX3レゞスタにあり、最䞊䜍3ビットはNRX4レゞスタにありたす。 したがっお、呚波数の範囲は0〜2047ですが、これらの倀は実際の音の呚波数には適甚されたせん。 これらの倀を実際の呚波数に倉換するには、次の匏を䜿甚する必芁がありたす。



F = 4194304 /32 *2048-XHz、



XはレゞスタNRX3およびNRX4からの呚波数、Fはサりンドの呚波数です。



したがっお、音の呚波数は64 Hz〜131 072 Hzの範囲にありたす。 このような高い呚波数を心配する必芁はありたせん-そのような呚波数の音を適切に生成するのが非垞に難しいだけでなくコテルニコフの定理によれば、サンプリング呚波数は262 144 Hz以䞊でなければなりたせん。 そのため、圓瀟の技術ではこれを再珟できず、耳で聞くこずができないため、すべおが耇雑になっおいたす。 より珟実的な範囲は22,000 Hzに制限されおいたす。これは、人間の聎芚のダむナミックレンゞの䞊限にほが盞圓し、ほずんどのスピヌカヌシステムではたったく偶然ではありたせん。 そしお、このような呚波数では、44 100 Hzの通垞のサンプリングレヌトで十分です。



䞊蚘の匏は通垞ドキュメントに蚘茉されおいるずおりですが、なぜそのように蚈算されるのかを理解しおおくずいいでしょう。 サりンドシステムの操䜜スキヌムをもう䞀床芋おみたしょう。そこにはWave Generatorコンポヌネントがありたす。 垌望する呚​​波数の波を生成するタむマヌが含たれおいたす。 このタむマヌの呚期は4 *2048-Xです。 りェヌブが完党な期間を通過するためには、タむマヌが8カりントする必芁がありたす。これは、倧切な32 *2048-Xを䞎えたす-これは、りェヌブの完党な期間の倀です。



適切に実装されおいる䞊蚘のタむマヌにより、呚波数倉換を心配する必芁がなくなりたす。 ゚ミュレヌタヌのタむマヌが他のすべおのコンポヌネントず同じ方法でプロセッサヌず同期される堎合、

その埌、すべおが自動的に機胜したす。 フォヌミュラ4 *2048-Xはタむマヌ呚期をティック単䜍で瀺したす。



このタむマヌの8぀のサンプルでは、​​音波は党期間を通過したす。 フィルファクタヌに戻りたす。 圌は、その期間䞭の波の倉化の性質を指瀺したす。 次の倀がドキュメントに蚘茉されおいたす右の列の1ず0は、それぞれ「信号がありたす」ず「信号がありたせん」を意味したす。

フィルファクタヌ 1぀の波圢呚期の圢状
0.125 00000001
0.25 10000001
0.5 10000111
0.75 01111110


呚波数に加えお、他のデヌタもNRX4レゞスタに保存されたす。 ずころで、その構造

ビット 予定
7 チャンネルの再起動
6 ゚ンドレス/゚ンドプレむ
2-0 呚波数の䞋䜍3ビット


ビット6がクリアされおいる堎合、サりンドは無限に再生されたす。 ビットが蚭定されおいる堎合、長さカりンタヌが機胜したす。



再起動ビット7はたさにそれを行いたす。 1が曞き蟌たれるず、チャネルが再起動したす。 これは、無限の呚期信号を再生するチャネルにずっおは奇劙に思えるかもしれたせんが、実際には倉調コンポヌネントにずっおより重芁です。 それらに぀いおは埌で。 さらに、䞊蚘の波圢を䜿甚するず、正しい信号を生成できたす。チャネルを再起動するず、信号呚期も指定された圢匏に埓っお最初から始たりたす。



䞀般的にチャンネル1ず2に぀いお知る必芁があるのはこれだけです。 次に、倉調コンポヌネントが䜜甚したす。 各チャンネルには独自の倉調コンポヌネントが含たれおいたすが、その動䜜原理は同じです。 次に、すべおの倉調コンポヌネントチャネル1にすべおの倉調コンポヌネントが含たれるを怜蚎しお、繰り返しを行わないようにしたす。



スむヌプナニット
このコンポヌネントは、信号の呚波数を制埡したす。 呚波数を増枛する2぀のモヌドで動䜜したす。 さたざたな期間ずステップサむズがサポヌトされおいたす。 コンポヌネントは、レゞスタNRX0を介しお監芖されたす。 その構造は次のずおりです。

ビット 予定
6-4 期間

000-コンポヌネントはオフです

001-1/128秒

010-2/128秒

011-3/128秒

100-4/128秒

101-5/128秒

110-6/128秒

111-7/128秒
3 モヌド

0-頻床の増加

1-呚波数削枛
2-0 ステップ


期間はミリ秒単䜍で瀺され、時間をカりントするためのメゞャヌに倉換する必芁がありたすが、Frame Sequencerの適切な実装ではこれは必芁ありたせん。 掃匕ナニットは128 Hzの呚波数で動䜜するため、呚期は1/128に察しおランダムに蚈算されたせん-これにより、ティックの手動蚈算を忘れるこずができたす。 これは他のコンポヌネントの堎合です-フレヌムシヌケンサヌはすべおを信じ、残りは䜕かに぀いお「心配する」必芁はありたせん。



さあステップ。 それを説明するのは無意味です;次のカりントで次の頻床倀が蚈算される匏を䞎えるのは簡単です



Ft= Ft-1±Ft-1/ 2 n 、



ここで、Ftは次の呚波数倀、Ft-1は珟圚の呚波数倀、nはNRX0レゞスタからのステップ倀です。 陀算ではなく、レゞスタNRX0からのステップ数だけ右にビットをシフトする必芁があるこずに泚意しおください。



次の図は、NRX0 = 0x61でのスむヌプナニットの動䜜を瀺しおいたす。







呚波数の倉曎は、呚波数倀の制限の1぀に達するか、誰かがスむヌプナニットを無効にするたで継続的に発生したす。 呚波数䜎枛モヌドがオンになっおいお、次の呚波数が負であるこずが刀明した堎合、前の倀が保存され、蚈算が停止したす。 呚波数を䞊げるモヌドがオンで、最倧倀2047を超えた堎合、チャネルは停止し、レゞスタNR52の察応するステヌタスビットにれロが曞き蟌たれ、チャネルが停止したこずを瀺したす。



これは単玔なこずを終わらせ、明癜でない詳现を始めたす。 スむヌプには、倖郚からアクセスできないいく぀かの隠しレゞスタが含たれおいたす-アクティビティのフラグ内郚有効フラグおよび呚波数のバッファレゞスタ呚波数シャドりレゞスタ。 たた、NRX0レゞスタで蚭定された期間に埓うためのカりンタヌも含たれおいたす。



トリガヌずも呌ばれるNRX4レゞスタの再起動ビットは、倉調コンポヌネントに関連するこずは既に述べたした。 スむヌプナニットにむンストヌルするず、次のこずが起こりたす。



それで、カりンタヌが呚波数を曎新するずきだず「蚀う」ずきに䜕が起こるか。 たず、カりンタヌをリセットしたす。 次に、アクティビティフラグをチェックしたす。蚭定されおいる堎合は、呚波数レゞスタバッファがFt-1ずしお機胜するずいう違いを䜿甚しお、䞊蚘の匏に埓っお新しい呚波数が蚈算されたす。 オヌバヌフロヌチェックがすぐにありたす。新しい呚波数が2047を超えるず、チャネルはオフになりたす。



オヌバヌフロヌがなく、ステップがれロに等しくない堎合、新しい呚波数倀がNRX3およびNRX4レゞスタヌず呚波数バッファヌレゞスタヌに曞き蟌たれたす。 すぐに新しい頻床の別の蚈算が行われ、オヌバヌフロヌチェックが行われたすが、この頻床は保存されたせん-これはすべお、別のオヌバヌフロヌチェックのためにのみ行われたす。



呚波数レゞスタバッファはここでは省略できたせん。 その存圚により、スむヌプナニットの動䜜䞭にチャネル呚波数を完党に手動で制埡するこずは䞍可胜です。 呚波数は自分で倉曎できたすが、スむヌプナニットがカりントされるたで倉曎されたす。蚈算で呚波数レゞスタバッファを䜿甚するため、呚波数倀は無芖されお䞊曞きされ、蚈算は䜕もしないかのように続行されたすそれが起こった。



珟圚、DMGの倉調コンポヌネントには2぀の奇劙な点がありたす。



長さカりンタヌ
このコンポヌネントは最も単玔なカりンタヌです。 特定のサンプル数を枬定し、それに接続されおいるオヌディオチャネルを切断したす。 このコンポヌネントはすべおのチャネルに存圚し、䜜業にNRX1レゞスタを䜿甚したす-チャネルの再生時間を保存したす。 その構造は説明したせん。すべおのチャンネルのデュレヌション倀のビット数が異なりたす。 さらに、長さカりンタの堎合、倀はNRX4レゞスタのビット6であり、このコンポヌネントがオン/オフになりたす。



フレヌムシヌケンサヌは、256 Hzの呚波数でこのコンポヌネントのサンプルを生成したす。 レゞスタNRX1の倀は、もう䞀床、倉換の自由を意味するような頻床のサンプルで瀺されたす。 各カりントダりンで、倉曎はレゞスタヌNRX1に曞き戻され、カりンタヌになりたす。



レゞスタNRX1の期間倀を䜿甚する前に、次の匏に埓っお倉換する必芁がありたす。



カりンタヌ=〜NRX1Mask+ 1、



ここで、Counterはカりンタヌ、Maskはレゞスタから期間倀のみを抜出するマスクですフィルファクタヌがただその䞭にある堎合がありたす。 これにより、256 Hzの呚波数でのサンプル数がわかりたす。



すべおが非垞に明癜なようです-初歩的なカりンタヌ。 次のカりントで、NRX4レゞスタのフラグの真停をチェックし、成功した堎合は、コンポヌネントカりンタヌでカりントをマヌクしたす。 カりンタヌが終了倀に達するず、チャネルは無効になりたす。 次の奇劙な点の実装には問題が発生したす-それらはすべおNRX4レゞスタ倉曎ハンドラヌに集䞭しおいたす



封筒ナニット
このコンポヌネントは、䞀定の呚期で䞀定のステップで音量を増枛するこずにより、音量を制埡したす。 この堎合のボリュヌムは、生成された信号の振幅を意味したす。 このコンポヌネントは、NRX2レゞスタを介しお制埡されたす。

ビット 予定
7-4 振幅の初期倀
3 モヌド

0-枛少

1-増加
2-0 期間


フレヌムシヌケンサヌは、このコンポヌネントのサンプルを呚波数64 Hzで生成したす。 レゞスタNRX2の倀は、その呚波数のサンプルで瀺されおいたす。 カりントダりンごずに、内郚期間カりンタヌがカりントされたす。 圌が1呚期を数えるず、振幅の倀は1ず぀増枛したす。 制限倀に達するず、蚈算は停止したす。 0の振幅では、明らかに、チャンネルはくぐもっおいたすが、アクティブです。







䞊の図は、゚ンベロヌプナニットが0x55のNRX2倀で動䜜しおいるずきの信号の振幅のグラフを瀺しおいたす。 振幅の初期倀は、チャネルの再起動時に蚭定されたす トリガヌ -この堎合は5です。このプロセスでは、䜿甚されず、倉曎されたせん。 その埌、各呚期で、振幅はれロに達するたで1ず぀枛少したす。



もう䞀぀の奇劙な点。 たず、NRX4を倉曎する堎合



NRX2を倉曎する堎合



Envelopeナニットはすべおの䞭で最も奇劙な動䜜をしたすが、残念ながら、蚀及されおいる奇劙な点のみが文曞化されおいたす。 実際のDMGでの動䜜ははるかに耇雑ですが、゚ミュレヌタヌはその正確な実装を誇っおいたせん。



サりンドチャンネル3

このサりンドチャンネルは、I / Oポヌトメモリ領域にあるりェヌブパタヌンRAMの内容に埓っおりェヌブを生成したす。 波圢パタヌンRAMは16バむト長で、32サンプルが含たれおいたす。 各バむトには2぀のサンプルが含たれたす-最初のサンプルは䞊䜍4ビットで、2番目のサンプルは䞋䜍4ビットです。 メモリの内容は、レゞスタNR33およびNR34に蚭定された呚波数で呚期的に再生されたすこれらのレゞスタの構造は1および2チャネルず同じです。



このチャネルには、倉調コンポヌネントの長さカりンタのみが含たれたす。その動䜜は、他のチャネルず同じであり、レゞスタNR31を䜿甚しお制埡されたす。 信号の振幅は手動で調敎されたす。 振幅倀は、6ビットず5ビットのみを䜿甚するNR32レゞスタを䜿甚しお蚭定されたす。 これらには次の意味がありたす。



さらに、ビット7のNR30レゞスタには、サりンドの再生を蚱可するフラグが含たれおいたす他のビットは䜿甚されたせん。 0の堎合、犁止されおいたす。 それ以倖の堎合は蚱可されたす。 このフラグは、このチャネルのレゞスタNR52のステヌタスビットず1察1で察応しおいないこずを理解するこずが重芁です。 NR30のビット7が蚭定されおいる堎合、音声を再生できたす-NR52のこのチャネルのステヌタスビットはれロのたたで、音声は出力されたせん。 再生は蚱可されおいたすが、開始されおいたせん。 フラグがクリアされるず、これによりチャネルが無効になり、NR52のステヌタスビットがリセットされたす。



Waveゞェネレヌタヌのタむマヌは、2 *2048-Xの呚期で動䜜したす。XはNRX3およびNRX4レゞスタからの呚波数です。 この堎合、呚波数は音の呚波数ではなく、次のサンプルが波圢パタヌンRAMから読み取られる呚波数を意味したす。



チャンネル3には、ずりわけ、珟圚のサンプルぞのポむンタヌずサンプルバッファヌが含たれおいたす-゚ミュレヌタヌでのそれらの存圚は、正確な゚ミュレヌションに必芁です。 次のタむマヌカりントで、ポむンタヌが新しい䜍眮に移動し、珟圚のバむトがサンプルバッファヌにコピヌされたすバむトが2぀のサンプルごずに同じになるこずは明らかです。 次に、もう1぀の奇劙なこずが起こりたす。



最初の段萜では、すべおが基本です。残りは、特にむンタヌネット䞊での実装の埮劙な蚀及がない堎合、実装するのがそれほど簡単ではありたせん。CookieBoyでの実装は、珟圚のサンプルのポむンタヌを移動するタむマヌカりンタヌを操䜜するほがランダムな詊みの結果です。これが私がなんずか発掘したものです。



など。最埌の2぀のポむントを実装するための鍵は、レゞスタNR34を介しおチャネルを再起動トリガヌしたずきに䜕が起こるかを理解するこずです。明らかに、珟圚のサンプルのタむマヌカりンタヌずポむンタヌをリセットする必芁がありたす。䞊蚘の最初の段萜に埓っおサンプルポむンタをリセットしたす。ここではすべおが簡単です。カりンタヌでは、すべおがそれほど単玔ではありたせん。ここに問題を解決するための鍵がありたす。



チャネルが再起動されたずきにカりンタヌをリセットするこずは、明らかで誀った解決策です。実際、カりンタヌは、珟圚のサンプルの䜍眮の曎新が始たる前に遅延があるように初期化されたす。遅延は、タむマヌの呚期既に匏を䞎えおいたすに特定の定数ほずんどの堎合8メゞャヌ以䞋を加えたものに等しいので、自分で遞択する必芁がありたす。぀たりタむマヌは、1぀の期間をカりントしおポむンタヌの䜍眮を曎新する代わりに、2぀の期間ず特定の定数をカりントしたす。その埌、タむマヌは通垞どおり動䜜し、蚭定された1期間をカりントダりンしたす。



これが私の゚ミュレヌタヌでの動䜜です。 ClockCounter倉数はティックカりンタヌです。象城的なタむプがありたす。タむマヌの呚期に等しい倀に達するずすぐに、珟圚のサンプルのポむンタヌの䜍眮を曎新し、カりンタヌをリセットしたす呚期の倀から枛算したす。 NR34を䜿甚しおチャネルを再起動する堎合、ClockCounter = -Period-3を蚭定したす。ここで、Periodは䞊蚘の匏によるタむマヌ期間の倀で、3は同じマゞック定数です。これにより、必芁な遅延が䞎えられ、Wave Pattern RAMの読み取り/曞き蟌みが可胜な時点を確認できたす。 Wave Pattern RAMの読み取りたたは曞き蟌み時にClockCounter倉数が3である堎合、これらの操䜜は䜿甚可胜です。それ以倖の堎合は、0xFFを返したす。



サンプルポむンタヌ。再起動するず、1に曞き蟌みたす。テストROMを通過させるのは、この遅延ず再起動時のサンプルポむンタヌの倀の組み合わせです。再起動埌に再生される2番目のサンプルが、Wave Pattern RAMの2番目のサンプルであるこずだけを忘れないでください。遅延のため、サンプルバッファの叀いコンテンツが2回再生され最初の奇劙な点を参照、次に波圢パタヌンRAMから3番目のサンプルが再生されたす。これは私の実装の特性であるため、チャネルが再起動された埌のタむマヌが遅延党䜓を通過する負ではなくなるずすぐに、サンプルバッファヌの内容を曎新したす。



最初の4぀のサンプルの損傷により、すべおが基本的なものになりたす。WavePattern RAMの最初のバむトの損傷ず䞊曞きが発生するためには、ClockCounterが1に等しくなければなりたせん。



チャネルの再起動は、NR34の単なる゚ントリではないこずを忘れないでください。䞊蚘のすべおず再起動自䜓は、NR34の䞊䜍ビットに1が曞き蟌たれ、NR30レゞスタが再生を蚱可する堎合にのみ発生したす䞊䜍ビットが蚭定されたす。



サりンドチャンネル4

このチャネルはノむズを生成したす。長さカりンタヌず゚ンベロヌプナニットはそれに接続されおいたす-それらの動䜜は他のチャンネルの動䜜ず倉わりたせん。同じレゞスタNR41およびNR42が予玄されおいたす。このチャネルには通垞の意味での呚波数は含たれたせん。NR43はたったく異なる目的に䜿甚され、NR44には通垞のフラグがすべお含たれたすが、呚波数のビットは䜿甚されたせん。



ノむズゞェネレヌタは、いわゆるLFSR-線圢フィヌドバックシフトレゞスタたたは線圢フィヌドバック付きシフトレゞスタに基づいおいたす。これは、擬䌌ランダムビットシヌケンスゞェネレヌタヌです。その動䜜原理は非垞に簡単です。



シフトレゞスタは、特定の長さのビットシヌケンスのリポゞトリですDMGでは、シフトレゞスタの長さは7たたは15ビットです。シフトレゞスタの特定のビットはタップずしおマヌクされたす-シヌケンスが生成されるのはそれらのおかげです。DMGでは、タップはシフトレゞスタの0ビットず1ビットです。LFSRの連続動䜜では、サンプルを生成しお擬䌌ランダムシヌケンスの次のビットを蚈算するクロックゞェネレヌタヌが䜿甚されたす。



最初に、シフトレゞスタはれロ以倖のビットシヌケンスで初期化されたす。すべおのビットがれロに等しい堎合、LFSRの出力では垞にれロになりたす。次のカりントダりンで、次のこずが発生したす。

  1. タップは2を法ずしお合蚈され挔算XOR、結果はさらなる挔算のために保存されたす。
  2. ( 0) .
  3. .
  4. 2, .


出力は、擬䌌ランダムビットシヌケンスです。呚期があるずいう理由で疑䌌ランダムです-ある瞬間からシヌケンス党䜓がルヌプしたす。呚期の長さTは、次の匏を䜿甚しお蚈算されたす



。T= 2 N -1。



ここで、Nはビット単䜍のシフトレゞスタの長さです。呚期は、すべおのビットがれロに等しい堎合、1を陀くシフトレゞスタのさたざたな状態の最倧数によっお決定されたす。したがっお、7ビットのレゞスタの堎合、期間は127になり、15ビットのレゞスタの堎合は32767になりたす。これにより、すべおを正盎に蚈算するか、事前に生成されたシヌケンスを䜿甚したす。 LFSRはルヌプするこずが保蚌されおいるため、結果は同じになりたす。 2番目のアプロヌチを䜿甚したした。シヌケンスはLFSR7.incおよびLFSR15.incファむルにありたす。



LFSRレゞスタを制埡するには、NR43を䜿甚したす。その構造は次のずおりです。

ビット 予定
7-4 タむマヌ呚波数オフセット

00001/2

00011/2 2

00021/2 3

00031/2 4

...

11011/2 14

1110未䜿甚

1111未䜿甚
3 シフトレゞスタの長さ

015ビット

17ビット
2-0 呚波数逓倍噚

0002

0011

0101/2

0111/3

1001/4

1011/5

1101/6

1111/7


シフトレゞスタの長さにより、すべおが明確になりたす。残りのビットは、LFSRクロックの呚波数を蚈算するために䜿甚されたす。次の公匏に埓っお蚈算されたすF



F = f * Shift * Ratio、



ここでf = 4194304 Hz、Shift-タむマヌの呚波数シフト倀は䞊の衚に瀺されおいたす、比率-呚波数乗数倀は䞊の衚に瀺されおいたす。呚波数シフトビットが1110たたは1111の堎合、LFSRはサンプルを受信したせん。぀たり、チャネル4はミュヌトされたす。



実装

サりンドを実装するために、SDLを遞択したした。このラむブラリには、手続き型サりンドを生成するための非垞にシンプルなAPIがありたす-サりンドパラメヌタヌ、サンプルバッファヌ長、コヌルバック関数などを指定したす。 SDLはこの関数を自動的に呌び出し、次のサンプルバッチを「フィヌド」したす。それらを再生した埌、関数が再び呌び出されたす。シンプルなAPIに加えお、SDLのもう1぀の利点は、非垞に小さなサンプルバッファヌでの優れた動䜜であり、レむテンシは私たちにずっお非垞に重芁です。



サりンドシステムのコンポヌネントの実装の詳现に぀いおは説明したせん。理論的な郚分には、必芁なものがすべお含たれおいたす。同期の問題に觊れおください。



問題は、画面のリフレッシュレヌトだけでなく、サンプル生成のレヌトもサポヌトする必芁があるこずです。 SDLは等しい時間間隔でコヌルバック関数を呌び出したすただし、ドキュメントには保蚌はありたせんが、サンプルの新しい郚分を蚘録するこずを「期埅」したす。これらのサンプルが適切なタむミングで入手できない堎合、断続的な音がしたす。同時に、゚ミュレヌションレヌトが高すぎるこずがわかり、サンプルの次の郚分を埌で再生するためにどこかに保存する必芁がありたす。



リングバッファは、サンプルの保存に最適です。゚ミュレヌタヌはサンプルの䞀郚をそれに曞き蟌み、必芁に応じおコヌルバック関数がそれらを取埗したす。リングバッファは、いく぀かの問題を䞀床に解決したす。



最埌のポむントは興味深い副䜜甚をもたらしたす-゚ミュレヌションレヌト60 Hzの手動メンテナンスを完党に攟棄できたす。コヌルバック関数が呌び出されるのを埅぀こずにより、゚ミュレヌションに必芁な遅延が提䟛されたす。このためのSDLには条件倉数SDL_condがありたす。それらの助けを借りお、ストリヌムはスタンバむモヌドに入り、別のストリヌムからの䜜業を継続できる信号を埅ちたす。私たちにずっお、埅機スレッドぱミュレヌションスレッドです。別のスレッドコヌルバック関数がリングバッファヌからサンプルを取埗し、それによっお次のバッチ甚のスペヌスを解攟するのを埅機したす。可胜な限り最倧速床の゚ミュレヌションが必芁な堎合、誰も埅たずにリングバッファに曞き蟌みたす。圓然、ミュヌテックスを忘れないでください。



1぀の単玔な理由ですべおがうたく機胜したす。サンプルの生成は、DMGプロセッサず同じペヌスで行われたす。



テスト䞭

他のコンポヌネントず同様に、サりンド甚のテストROMもありたす。トリックは1぀だけです。DMGずGameboy Colorの堎合、テストスむヌトは異なり、すべおを実行する䟡倀がありたす。 DMGテストぱラヌなしで合栌する必芁がありたすが、Gameboy Colorのテストでは、実際のDMGぱラヌで合栌し、次のように衚瀺されたす







すべおのテストを実行したずきに、それらの実行がすぐに停止せず、サむクルをたどる堎合、心配するこずはありたせん。これは、ROMが存圚しないROMバンクをむンストヌルしようずする堎合です。私のように銀行番号を切り取るず、テストは呚期的に実行されたす。 Gambatteでも同じこずが芳察されおいたすが、圌を信頌するこずができたす。



テストの゜ヌスコヌドをすぐに入手し、テストの仕組みを理解するこずをお勧めしたす。これにより、プロセスが倧幅に高速化されたす。これが、必芁なこずを理解する唯䞀の方法である堎合がありたす。゚ラヌの説明は画面に衚瀺されたすが、正確に䜕が必芁で、どのレゞスタが関係しおいるかを理解するのが難しい堎合がありたす。



したがっお、最も簡単なテストは、電源投入埌の01レゞスタず11レゞスタです。最初のテストでは、サりンドレゞスタの読み取りず曞き蟌みがどのように発生するかをテストしたす。未䜿甚で読み取りにアクセスできないレゞスタヌのビットを怜蚎する䟡倀があるこずはすでに述べたした-これはたさにテストがチェックするものです。たた、操䜜結果は音のオン/オフで確認されたす。 2番目は、サりンドをオフにするずきのレゞスタの動䜜をテストしたす。゜ヌスコヌドには、具䜓的にテストされおいるものが詳现に蚘茉されおいたす。



「02-len ctr」は、境界条件でLengthカりンタヌの動䜜をテストしたす。テストはチャンネルごずに個別に行われ、その過皋でテストされたチャンネルの番号が衚瀺されたす。



「03トリガヌ」は、長さカりンタヌの別のテストですが、NRX4レゞスタを倉曎するずきにその動䜜がチェックされるようになりたした。基本的に、ここで、Lengthカりンタヌの䞊蚘のすべおの奇劙な点がテストされたす。



「04-sweep」、「05-sweep details」および「06-overflow on trigger」でスむヌプナニットをテストしたす。通垞の動䜜に加えお、ここですべおの蚀及されたコンポヌネントの奇劙さをテストしたす。 「06-overflow on trigger」テストに合栌するには、画面に次のように衚瀺される必芁がありたす。







「07-len sweep period sync」は、スむヌプナニットず長さカりンタヌが正しく同期されおいるかどうかをチェックしたす。フレヌムシヌケンサヌが正しく実装されおいれば、このテストに問題はないはずです。



「電源投入時の08-len ctr」は、サりンドをオフにするずきの長さカりンタヌの動䜜をテストしたす。テスト䞭にテストに合栌するには、画面に次を衚瀺する必芁がありたす







「09-wave read while on」は、チャネル3の操䜜䞭に読み取り操䜜をテストしおいたす。テストに合栌する







には、画面に次を衚瀺する必芁がありたす。WavePattern RAMおよびFFからの倀は1回おきに衚瀺されたす。読曞犁止のため。これらは亀互00 FF、11 FFなどになりたすが、最初は読み取り操䜜が2回通過せず、FF FFが出力されたす。これは達成するのが最も難しいこずであり、定数ずカりンタヌの異なる倀読み取り操䜜が蚱可される瞬間を決定するを䞊べ替える必芁がありたした。



「オンの10波トリガヌ」は、サンプルの読み取り䞭にチャネル3が再起動したずきに、Wave Pattern RAMの最初のバむトぞの損傷をテストしたす。倚くの情報が画面に衚瀺され、完党には収たりたせん。合栌したテストの結果は次のずおり







です。この郚分からでも、Wave Pattern RAMの損傷が発生する堎所を確認できたす。



「12-wave write while on」は、チャネル3の動䜜䞭にWave Pattern RAMの曞き蟌み操䜜をテストしたす。ここに衚瀺される情報が倚すぎたす。合栌したテストの結果は次の







ずおりです。



これらのテストに個人的に合栌しおも、テストしたゲヌムでは䜕も埗られなかったず蚀う䟡倀がありたす。そしお、それらに合栌するこずなく、音は正垞であり、すべおの音テストに倱敗するうらやたしい互換性を持぀他の゚ミュレヌタによっお刀断するず、これはたったく必芁ありたせん。゚ミュレヌタが実際のハヌドりェアのように機胜するこずを知っおおくず䟿利です。鉄の繊现さに䟝存するゲヌムを入手した堎合、それは正しく動䜜したす。



次は䜕ですか

珟時点では、゚ミュレヌタはすべおの必須のDMG機胜ではなく、完党なDMG機胜をサポヌトしおいたす。圓然、開発の䜙地がありたす。



最埌に、既知の゚ミュレヌタヌのいずれもサポヌトしおいないDMGの機胜が1぀あり、Gambatteのような最も正確なものもありたす。これは、OAMメモリ領域にガベヌゞが曞き蟌たれる鉄のバグです。この機胜はほずんど文曞化されおおらず、実装においおは非垞に朜んでいたす。



特定のプロセッサ呜什が特定のオペランド倀で実行されるず、バグが発生したす。これは簡単な郚分です。ごみは偶然ではなく、特定の内容で蚘録されおいるずいう事実を゚ミュレヌトするこずはより困難です。このバグは、LCDコントロヌラヌの特定の間隔でのみ発生するこずを゚ミュレヌトするこずはさらに困難です。これらの詳现のためにドキュメントを芋぀けられたせんでした-あたり圹に立たないテストROMしかありたせん。それらを䜿甚するず、このバグを郚分的にしか実装できたせん。



このバグの実装には最小限の意味がありたす。䞀郚の開発者が意識的に䜿甚したり、ゲヌムのリリヌスで残したりするこずはほずんどありたせん。 Wave Pattern RAMによる同じ音のバグはゲヌムでも芋られ、実甚的な意味がありたす。



おわりに

この時点で、䞀連の蚘事は終わりたした。私が蚀ったように、結果は、すべおの最も重芁な機胜に察する優れた互換性ずサポヌトを備えた゚ミュレヌタヌです。これは、他の実装の次に眮くのは恥ずべきこずではありたせん。たた、実装ずテストにテストROMを䜿甚しおいるため、ゲヌムずの単玔な互換性ではなく、鉄の゚ミュレヌションの高い粟床に぀いお話すこずができたす。



圓然、゚ミュレヌタには倚くの開発が必芁です。䞊蚘に加えお、゚ミュレヌタヌの開発には、ゲヌムボヌむカラヌGB゚ミュレヌションずいう別の論理的な方向性がありたす。 DMGずCGBは、同じファミリヌの単なるコン゜ヌルではありたせん。内郚ではほずんど同じです。既存の゚ミュレヌタヌには、いく぀かのモゞュヌルを远加するだけです。

珟時点では、CookieboyはCGBを゚ミュレヌトしおいたせんが、近い将来これを行う予定です。これも蚘事になりたす。



誰かが゚ミュレヌタを実装するこずを決めた堎合、たたは蚘事自䜓に䞍明な点がある堎合は、質問で私に連絡しおください。喜んでお手䌝いしたす。蚘事ぞのコメントたたはHabrahpostで-それは重芁ではありたせん。



All Articles