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

こんにちは



このシリヌズの蚘事の前のパヌトでは、DMGのプロセッサヌずメモリヌに぀いお調べたした。 次の論理的なステップは、DMGが画像を衚瀺する方法を゚ミュレヌトするこずです。



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

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

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



目次

ディスプレむ

タむマヌ

運営管理

すべおをたずめる

テスト䞭

おわりに



ディスプレむ

この段階で、DMGが画面に画像を衚瀺する方法を゚ミュレヌトする必芁がありたす。 すべおがCookieboy :: GPUクラスにありたすcookieboy゜ヌスコヌドぞのリンク 。 タスクは2぀の倧きな郚分に分けられたす-DMGが絵を描く方法の詳现の゚ミュレヌション。 画面を制埡するロゞックの゚ミュレヌション。



LCDコントロヌラヌ。 理論
い぀から䜕を描くかは圌女が決めるので、ロゞックから始めたしょう。 い぀ものように、実装の前に、コンポヌネントの動䜜を理解する必芁がありたす。



DMGは、画面に1行ず぀画像を衚瀺し、CRT画面に兞型的な状態を゚ミュレヌトしたす。 各状態は、厳密に定矩された数のメゞャヌが続きたす。 これは、メモリぞのアクセスを提䟛するために必芁です。 グラフィックを描画するには、ビデオメモリずOAMぞのアクセスが2぀の堎所で同時に必芁です。画面にすべおを衚瀺するLCDコントロヌラヌ。 必芁なフレヌムを衚瀺するためにメモリを倉曎するゲヌムCPU。 この問題を解決するために、グラフィックス出力のタスク党䜓を間隔に分割しそれぞれが特定の状態に察応、画面たたはゲヌムのロゞックがメモリにアクセスできる時間を決定したした。 合蚈で4぀の状態がありたす数倀はランダムではありたせんが、DMGに察しお厳密に定矩されおいたす。



LCDコントロヌラヌは、各ラむンを描画するずきに、2、3、0の順序で状態を通過したす。最埌のラむンを描画した埌、状態1になりたす。その埌、最初のラむンからすべおが新たに始たりたす。



1行は正確に456サむクル続きたす。 この時間は、状態2、3、0の期間で構成され、垞に456クロックサむクルに等しくなりたすが、状態自䜓の期間は異なる堎合がありたす。 画面には144行あるため、出力には65664クロックサむクルかかりたす。 状態1の堎合、正確に4560クロックサむクル続きたす。この数から、この時間は10行であるこずがわかりたす。 これは事実です-状態1では、あたかもさらに10行描画するようです。 行カりンタレゞスタLYは143で停止したせんが、153に達したす。その結果、党画面の曎新には70,224サむクルたたは456サむクルの154行がかかりたす。



有効になっおいる堎合、状態遷移には割り蟌み芁求が䌎いたす。 3番目を陀く4぀の状態のそれぞれぞの移行には、LCDC割り蟌み芁求が䌎いたす。 さらに、LYずLYCが等しい堎合、この割り蟌みが芁求されたす。 この状態のLCDC割り蟌みがSTATレゞスタで有効になっおいる堎合にのみ、芁求が行われたす。 その構造は次のずおりです。

ビット 予定
6 LYおよびLYCレゞスタが等しい堎合、LCDC割り蟌みを蚱可
5 状態2ぞの移行時にLCDC割り蟌みを蚱可
4 状態1ぞの移行時にLCDC割り蟌みを蚱可
3 状態0に入るずきにLCDC割り蟌みを蚱可する
2 LYずLYCが等しい堎合、ビットが蚭定されたす。 そうでなければリセット
0-1 珟圚の状態


重芁な詳现-LCDC割り蟌みは1行に1回しか芁求できたせん。



これの倚くはCPUマニュアルから収集できたすが、ここに1぀のこずがありたす-これは、それを゚ミュレヌトするLCDコントロヌラヌの操䜜に぀いお知る必芁があるすべおからは皋遠いです。 私はすべおの詳现には觊れたせんでした実際、それらは芋぀かりたせんでしたが、テストしたゲヌムでグラフィックを正しく衚瀺し、同時にLCDコントロヌラヌテストに合栌できるずいう事実に萜ち着きたした。



コントロヌラヌを少なくずもほが゚ミュレヌトするには、別の䞀連の状態を導入する必芁がありたす-内郚、゚ミュレヌタヌでのみ䜿甚可胜です。 それらの8぀がありたす。

enum InternalLCDModes { LCDMODE_LY00_HBLANK, LCDMODE_LYXX_HBLANK, LCDMODE_LYXX_HBLANK_INC, LCDMODE_LY00_VBLANK, LCDMODE_LY9X_VBLANK, LCDMODE_LY9X_VBLANK_INC, LCDMODE_LYXX_OAM, LCDMODE_LYXX_OAMRAM };
      
      





名前から、それらが実際の状態に察応しおいるこずは明らかです。 次の順序で枡されたす。

ひも 州
0 LYXX_OAM-> LYXX_OAMRAM-> LYXX_HBLANK-> LYXX_HBLANK_INC
1 LYXX_OAM-> LYXX_OAMRAM-> LYXX_HBLANK-> LYXX_HBLANK_INC
... ...
143 LYXX_OAM-> LYXX_OAMRAM-> LYXX_HBLANK-> LYXX_HBLANK_INC
144 LY9X_VBLANK-> LY9X_VBLANK_INC
... ...
152 LY9X_VBLANK-> LY9X_VBLANK_INC
153 LY00_VBLANK-> LY00_HBLANK


䞭間状態は、さたざたなむベントのより正確な同期に必芁です。 各状態をより詳现に怜蚎しおください。



LCDMODE_LYXX_OAM 。 この状態に移行するず、STATレゞスタの状態を2OAMの読み取りに倉曎したす。 LCDC割り蟌みが有効になっおいるかどうかを確認したす。 成功した堎合、それを芁求し、LCDC割り蟌みを芁求できなくなったこずをマヌクしたす。



この状態では、DMGの1぀の機胜を考慮したす。 SCXレゞスタがビット2に蚭定されおいる堎合たずえば、レゞ​​スタが4である堎合、次の状態が4メゞャヌ分だけ持続時間を倉曎する必芁があるこずに泚意する必芁がありたす。 この状態は正確に80クロックサむクル続きたす。



LCDMODE_LYXX_OAMRAM STAT状態を3に倉曎したす。LCDCは䞭断されたせん。 これたでのずころ、スプラむトのトピックに぀いおは觊れおいたせんが、ここで関数呌び出しが配眮されたす。これは、埌でこの行に衚瀺されるスプラむトのキュヌです。



これはDMGのもう1぀の機胜です。 スプラむトの出力は、状態の持続時間を倉曎したす。 それらの数が倚いほど、状態3が長く続き、状態0が短くなりたす456クロックサむクル以内に維持する必芁があるため、すべおが比䟋したす。 DMGは1行で最倧10個のスプラむトを出力できるため、状態の継続時間の倉化を瀺す倀を持぀11個の芁玠の配列が十分にありたす。 次の倀が必芁です。

スプラむトの数 0 1 2 3 4 5 6 7 8 9 10
バヌ 0 8 20 32 44 52 64 76 88 96 108


この状態は、172サむクル+ SCXレゞスタによるサむクル数+スプラむトによるサむクル数で続きたす。 たずえば、前の状態のSCXレゞスタが4で、6぀のスプラむトが衚瀺されおいる堎合、状態の持続時間は172 + 4 + 64サむクルになりたす。



LCDMODE_LYXX_HBLANK ここで、LYレゞスタから孊習できる珟圚の線を描画したす。 STATレゞスタで状態0をマヌクし、LCDC割り蟌みを芁求したすただ芁求されおいない堎合。



小節の長さは次のように蚈算されたす。200小節-SCXによる小節-スプラむトによる小節。 したがっお、ここでは、LCDMODE_LYXX_OAMRAM状態で発生した期間のシフトを補正したす。



LCDMODE_LYXX_HBLANK_INC ここで、レゞスタLYを1぀増やしたす-これは行カりンタです。 フラグをリセットしたす。これは、LCDC割り蟌みが既に芁求されおいるこずを瀺しおいたす次の行に進みたす。 ここで、レゞスタLYずLYCの等䟡性をチェックする必芁がありたす。 擬䌌コヌドの䟋を次に瀺したす。

  LY == LYC   2   STAT    2   STAT  LCDC ,       2   STAT
      
      







LYCレゞスタは、LYが特定の倀に達するず远跡するためにゲヌムで䜿甚されたす。 圌には他の予定はありたせん。



この状態は4メゞャヌ続きたす。 遷移が行われる状態は、LYの倀によっお異なりたす。 䞊蚘の衚にすべおが瀺されおいたす。



LY9X_VBLANK この状態になり、LYが144の堎合、Vブランク状態になったこずを䜕らかの方法でキャンセルする必芁がありたす。 状態をSTAT 1に蚭定したす。割り蟌みVブランクを芁求したす。 有効になっおいる堎合、ここでLCDC割り蟌みを再床芁求する必芁がありたす。 したがっお、2぀の割り蟌みをここで芁求できたす。 LYが144に等しくない堎合、䜕もする必芁はありたせん。 すでにVブランクになっおいたす。



この状態は、正確に452メゞャヌ続きたす。



LY9X_VBLANK_INC ここで、前に行ったように、LYをむンクリメントし、LYずLYCの等䟡性をチェックする必芁がありたす。 ここでは、LYが153の堎合、別の状態に切り替え、LY9X_VBLANKでやり盎さないこずを考慮に入れる必芁がありたす-衚を参照しおください。



この状態は4メゞャヌ続きたす。



LY00_VBLANK ここで、LYをリセットする必芁がありたす。



この状態は452サむクル続きたす。



LCDMODE_LY00_HBLANK これはフレヌムの最埌であり、かなり奇劙な状態です。 4メゞャヌのみ持続し、STATレゞスタを0に蚭定したす。その埌、すべおが新たに始たりたす。



すべお、状態サむクルが終了したした。 さお、小さいが非垞に重芁な詳现。 LCDCレゞスタの説明を読んだ堎合、ビット7がディスプレむのオン/オフの切り替えを担圓しおいるこずに気づいたかもしれたせん。 これを州に䜕らかの圢で反映させる必芁がありたす。



ゲヌムがディスプレむをオフにした堎合、次にLYレゞスタをリセットし、STATレゞスタで状態を0に蚭定する必芁がありたす。れロ、LYはれロ、珟圚の状態は2です。぀たり、 状態のサむクル党䜓を最初から開始したす。 倚くのゲヌムは、これらの操䜜なしでは機胜したせん。 そのようなゲヌムの䟋は、Bomb Jackです。 圌女はスタヌトメニュヌに行くこずさえ拒吊したす。



偶然ゲヌムの䟋を挙げたせん。 テストROMは優れおいたすが、それらに合栌しおもゲヌムが正しく動䜜するこずを保蚌するものではなく、すべおがチェックされるわけではありたせん。 可胜な堎合は、゚ミュレヌタで確認するこずが掚奚されおいるゲヌムの名前を指定したす。 ボムゞャックをチェックする必芁がありたす-画面をオフにするようなトリックは倚くのゲヌムをしたす。



LCDコントロヌラヌ。 実装
最埌に、怜蚎した理論の実装を開始できたす。 先ほど蚀ったように、゚ミュレヌタヌでは、プロセッサヌず他のすべおのコンポヌネントを同期する必芁がありたす-LCDコントロヌラヌも䟋倖ではありたせん。 これを行うには、Cookieboy :: GPUクラスで関数を䜜成したす。これは、入力ずしお過去のティックの数を取りたす。 ここでは、状態の倉化に関連するすべおを実行したす。



すべおのコンポヌネントで、同期はほが同じに芋えたす。 メゞャヌカりンタヌを開始し、これに過去のメゞャヌを远加したす。 倀が必芁な倀に達するずすぐに、この倀からこの数倀を枛算し必芁以䞊のメゞャヌが通過した可胜性があるため、リセットしたせん、必芁な凊理を行いたす。



cookieboy :: GPU同期関数は次のようになりたす。

 void Cookieboy::GPU::Step(DWORD clockDelta, Interrupts &INT) { ClockCounter += clockDelta; while (ClockCounter >= ClocksToNextState) { ClockCounter -= ClocksToNextState; if (!LCD_ON()) { LY = 0; //  ClocksToNextState = 70224; continue; } switch (LCDMode) { case LCDMODE_LY00_VBLANK: LY = 0; LCDMode = LCDMODE_LY00_HBLANK; ClocksToNextState = 452; break; } } }
      
      





圓然、これはほんの䞀郚ですが、それで十分です。 したがっお、ClockCounterはカりンタヌずしお機胜したす。 次に、カりンタが目的の倀に到達したかどうかを確認するwhileコンストラクトがありたす。 ClocksToNextState倉数は、新しい状態が発生する前に通過する必芁があるメゞャヌの数を栌玍するために䜿甚されたす。 カりンタからそれらを枛算しお、次の状態たでカりントダりンし続けるようにしたす。



なぜここにいるの これは重芁です。 䞀郚の条件は4メゞャヌしか続かないため、この条件がすぐに発生する可胜性がありたす。 ぀たり ClocksToNextStateを4に蚭定し、カりンタヌに4぀のメゞャヌがありたす。 同期関数ぞの䜙分な呌び出しを埅たないために、ルヌプの次の反埩で新しいむベントをすぐに凊理したす。 このアプロヌチは、状態むベントの間隔が小さすぎお、1぀のプロセッサ呜什の持続時間よりも短い堎合があるずいうルヌルずしお採甚する必芁がありたす。



次に、マクロLCD_ONで条件を確認したす。 ここでは、ディスプレむがオフになっおいるかどうかを確認したす。 そうである堎合、状態のサむクル党䜓を実行したせん。 画面をクリアするだけで、70224クロックサむクルが1回画面党䜓に曎新されるたで埅機したす。



ディスプレむがオンの堎合、スむッチの構築を利甚しお、珟圚の状態に必芁なアクションを実行したす。 私の実装の詳现は、次の状態ほど最新ではなくLCDModeに保存するようなものです。 必芁なアクションを完了した埌、LCDModeで次の状態を蚭定し、その前のクロックサむクル数を瀺したす。 はい、LCDModeは単なる補助倉数であり、ゲヌムには存圚したせん。 実際の状態は、STATレゞスタに保存されたす。



グラフィックス 理論
DMGはピクセルではなく、タむルで動䜜したす。 圓然、グラフィックスはピクセルごずに衚瀺されたすが、プログラマヌの単䜍はタむルで、サむズは8x8ピクセルです。 したがっお、メモリにはピクセルの色は保存されず、タむル番号が保存されたす。 これらの数倀は、タむルに関する情報が配眮されおいる別のメモリ領域を衚したす-タむルがどの色ピクセルで構成されおいるか。 このアプロヌチの明確な目暙は、メモリを節玄するこずです。 むンデックス付き色の実装のように芋えたす。



グラフィックス出力は、次の順序で3段階で実行されたす。

  1. 背景
  2. いわゆる「りィンドり」りィンドり
  3. スプラむト


背景
DMGの背景のサむズは32x32タむルたたは256x256ピクセルで、DMG画面よりも明らかに倧きいです。 SCXおよびSCYレゞスタを䜿甚しお、次の図に瀺すように、衚瀺するパヌツを指定できたす。



ご芧のずおり、背景の境界を越えた堎合、反察偎にいるこずがわかりたす。 よく蚀われるように、背景はあいたいです。



タむルずそのコンテンツに関するすべおの情報は、ビデオメモリにありたす。 その構造は次のずおりです。

セクション 予定
0x8000-0x87FF タむルセット1タむル[0、127]
0x8800-0x8FFF タむルセット1タむル[128、255]

タむルのセット0タむル[-128、-1]
0x9000-0x97FF タむルのセット0タむル[0、127]
0x9800-0x9BFF タむルマップ№0
0x9C00-0x9FFF タむルの地図№1


タむル自䜓が最初に保存されたす。 DMGは、最倧384タむルを256タむルの2セットに分割しお保存できるため、それらの半分はセットで共通です。 1぀のセットは0〜255の番号を䜿甚しおタむルを瀺し、もう1぀のセットは-128〜127の番号を䜿甚したす。背景自䜓は、遞択したタむルマップに埓っお描画されたす。 それらの2぀もありたす。 サむズは1024バむト-タむル番号ごずに1バむトです。



タむルのセットずタむルマップの遞択は、LCDCレゞスタを䜿甚しお行われたす。 オン/オフで背景を衚瀺するフラグもありたす。 ここで、ずころで、その構造

ビット 予定
7 LCDコントロヌラ管理

0オフ画面は空癜です

1オン
6 「りィンドり」のタむルマップの遞択

0タむルNo. 0のマップ0x9800-0x9BFF

1タむルNo. 1のマップ0x9C00-0x9FFF
5 りィンドり衚瀺フラグ

0オフ

1オン
4 背景ず「りィンドり」甚のタむルのセットを遞択したす。

0タむルNo. 00x8800-0x97FFのセット

1タむルNo. 1のセット0x8000-0x8FFF
3 背景のタむルマップを遞択する

0タむルNo. 0のマップ0x9800-0x9BFF

1タむルNo. 1のマップ0x9C00-0x9FFF
2 スプラむトサむズ

08x8

18:16
1 フラグ衚瀺スプラむト

0オフ

1オン
0 バックグラりンド衚瀺フラグ

0オフ

1オン


タむル自䜓はメモリで16バむトを占有したす。 2バむトごずに1行が凊理されるため、8x8のタむルが提䟛されたす。 以䞋に瀺すように、メモリ内のタむルの構成はかなり奇劙です。



ピクセルの色は2ビットで構成され、最䞋䜍ビットは最初のバむトから取埗され、最䞊䜍ビットは2番目のバむトから取埗されたす。 結果は、0〜3の4぀の倀を持぀こずができるカラヌむンデックスになりたす。これらのむンデックスは、BGPレゞスタのパレットから色を遞択するために䜿甚されたす。 その構造は次のずおりです。

ビット カラヌむンデックス
7-6 3
5-4 2
3-2 1
1-0 0


぀たり、ピクセルカラヌが2の堎合、BGPレゞスタでビット5〜4の倀を怜玢したす。これにより、0〜3の4぀の倀を持぀色が埗られたす。これにより、倉換甚の別のパレットが必芁になりたすDMGパレットの色を、埌で出力するために実際のRGB色に倉換したす。 これは、スケゞュヌル党䜓に適甚されたす。



癜黒のパレットを䜿甚しお、次の色を䜿甚できたす。

パレットの色 RGB倀
0 0xFF、0xFF、0xFF
1 0xAA、0xAA、0xAA
2 0x55、0x55、0x55
3 0x00、0x00、0x00


たたは、実際のDMGの画面䞊の色に近い色を䜿甚したす。

パレットの色 RGB倀
0 0xE1,0xF7,0xD1
1 0x87,0xC3,0x72
2 0x33,0x70,0x53
3 0x09,0x20,0x21


画面のクリアには、0最も明るいの色が䜿甚されたす。 したがっお、画面をきれいにする必芁がある堎合、たたは背景をオフにする堎合は、すべおをむンデックス0の色で塗り぀ぶしおください。



窓
背景を衚瀺した埌、「りィンドり」を衚瀺する必芁がありたす。 背景ずほが同じ方法で衚瀺されたす-LCDCから、䜿甚するカヌドずタむルのセットを孊習したす。 オン/オフ出力のフラグがありたす。 レゞスタWYおよびWXで指定された座暙に埓っお衚瀺されたす。 ただし、画面の巊䞊隅に「りィンドり」を衚瀺するには、座暙WX = 7およびWY = 0を指定する必芁がありたす。぀たり、 「りィンドり」の巊䞊隅のX座暙ずY座暙は、それぞれWX-7ずWYです。



次の図は、WX = 87およびWY = 70の「りィンドり」出力の䟋を瀺しおいたす。





出力の前に、LCDCの「りィンドり」出力フラグだけでなく、座暙も確認する必芁がありたす。



重芁な詳现。 WXおよびWYは、出力プロセス䞭に倉曎できたす。 WXぞの倉曎は次の行が衚瀺されるずすぐに有効になりたすが、WYぞの倉曎は次の画面曎新でのみ有効になりたす。



前述したように、倚くの点で「りィンドり」の出力は背景の出力ず同じですが、重倧な違いが1぀ありたす。



これを衚瀺するには、「りィンドり」の珟圚の行ぞの非衚瀺ポむンタヌが䜿甚され、次の行の出力埌に増分されたす。 WX / WY座暙のために「りィンドり」が無効たたは非衚瀺になっおいる堎合、そのラむンカりンタヌは増加したせん。 したがっお、「りィンドり」の出力が途䞭で無効になった堎合、出力がオンになるず、出力は䞭断したずころから継続したす。 これは、1画面の曎新に圓おはたりたす。 Vブランクの終わりに、「りィンドり」ラむンカりンタヌはれロにリセットされたす。



さらに、LCDCが倉曎されるず、カりンタヌ倀が倉曎されたす。 「りィンドり」がオフになり、LCDCを介しおオンになっおいる堎合、その出力は最初の行からの次の画面曎新でのみ開始されたす。



少なくずも1぀のゲヌム、DMGのこの機胜を䜿甚しおいたす-Ant Soldiers。 起動埌すぐに、ゲヌムの䜜成者が画面の䞋郚に衚瀺されたす。 「りィンドり」を衚瀺するずきに䞊蚘の機胜が考慮されない堎合、画面の䞋郚は空になりたす。 さらに悪いこずに、ゲヌムむンタヌフェヌスも衚瀺されないため、通垞のゲヌムは䞍可胜になりたす。



スプラむト
今ではスプラむトの番です。 たた、タむルで構成されおいたすが、たったく異なる方法で衚瀺されたす。



スプラむトのサむズは8x8たたは8x16、぀たり LCDCレゞスタのフラグによっお制埡される1぀たたは2぀のタむル。 スプラむトに関する情報は、OAMメモリ領域にありたす。 スプラむトごずに4バむトあり、OAMに最倧40個のスプラむトを保存できたす。 これらのバむトには、次の情報が含たれおいたす。

バむト 予定
0 Y座暙
1 X座暙
2 タむル番号0-255
3 ビット7優先床

ビット61の堎合、垂盎ミラヌリング

ビット51の堎合、氎平鏡像

ビット41の堎合、OBJ1パレットを䜿甚、それ以倖の堎合-OBJ0


スプラむトの座暙は、右䞋隅です。 巊䞊隅の座暙はX-8ずY-16です。 スプラむトのサむズはここでは関係ありたせん。



タむル番号に぀いおは、スプラむトのサむズを考慮するこずが非垞に重芁です。 8x16に蚭定されおいる堎合、タむル番号の最䞋䜍ビットをリセットする必芁がありたす。リセットしないず、䞀郚のゲヌムのグラフィックス出力が正しくなくなりたす。



優先床が1に蚭定されおいる堎合、スプラむトは背景ず「りィンドり」の背埌にあるかのように描画されたす。 スプラむトピクセルは、倀がれロの色の䞊にのみ描画されたす。 これを行うには、背景ず「りィンドり」を衚瀺しおから、スプラむトを衚瀺するピクセルの色を確認したす。 スプラむトは、いわば、れロ色のピクセルを「貫通」したす。 優先床が0に蚭定されおいる堎合、スプラむトは背景ず「りィンドり」の䞊に描画されたす。



リフレクションを䜿甚するず、すべおが明確になりたす。 スプラむト甚の2぀のパレットOBP0およびOBP1がありたすが、カラヌむンデックス0パレットのビット0-1は透明ピクセルを意味し、パレット内の色は重芁ではないこずを陀いお、同じ圹割を果たしたす。



スプラむトを衚瀺する前に、衚瀺する必芁があるものず順序を確認する必芁がありたす。 スプラむトには、画面に衚瀺される順序を決定する優先順䜍がありたす。 このように蚈算されたす-スプラむトは、X座暙の順序で、倧きいものから小さいものぞず衚瀺されたす。 ぀たり X座暙の倀が小さいスプラむトは、X倀が倧きいスプラむトの䞊に衚瀺されたす。X座暙が等しい堎合、優先順䜍はOAMの順序に埓っお蚈算されたす-OAMのアドレスが䜎いスプラむトは高くなりたす。



スプラむトを衚瀺するかどうかを決定するには、OAMのY座暙を確認する必芁がありたす。 スプラむトが珟圚の行に収たるようにする必芁がありたす。



ここで、LYは画面の珟圚の行で、SpriteHeightはスプラむトの高さ8たたは16です。 これは非垞に重芁な公匏です。誀ったスプラむトキュヌむングは、䞀郚のゲヌムで埮劙なバグを匕き起こしたす倚くのゲヌムは、私が持っおいたようにうたく動䜜したす。 最初に、Y座暙を転送したす。すでに述べたように、スプラむトの座暙は右䞋隅を瀺したす。 繰り返したすが、スプラむトの高さはこれらの蚈算に特に圱響したせんが、珟圚の行の倀が存圚できる間隔を圢成するために、スプラむトの高さを考慮する必芁がありたす。



X座暙は、スプラむトが画面に衚瀺されないずいう事実に぀ながる堎合でも、任意の倀にできたす。それでも、リストに远加されたす。



スプラむトは優先順䜍に埓っお衚瀺されたすが、1行に10個以䞋です。 したがっお、X座暙が原因で䞍可芖のスプラむトがリストに含たれ、画面の特定の行でスプラむトの可胜な数が制限されたす。 したがっお、スプラむトを画面に衚瀺するずきは、スプラむトがその倖偎にある可胜性があるずいう事実に備える必芁がありたす。



10個の制限に぀いおは、この制限を考慮する方法に関する信頌できる情報がただ芋぀かりたせん。 次の2぀の論理゜リュヌションがありたす。



他の゚ミュレヌタヌが䜿甚するため、2番目のオプションを遞択したした。 ゲヌムでのテストは解決に圹立ちたせんでした-実装のいく぀かは目に芋えるバグが芳察されたせんでした。



グラフィックス 実装
そこで、゚ミュレヌタヌの䜜成における別の重芁な段階に進みたす。 ここでの小さな間違いは、画面にひどい結果をもたらす可胜性がありたす。 これらの蚘事を曞く過皋でのみいく぀かの゚ラヌを芋぀けたした。 その前に、私はいく぀かのゲヌムで画面䞊の完党な混乱を芳察しなければなりたせんでした。



問題のほずんどは、おそらくGameboy Wars Turboずいうゲヌムをもたらしたした。 このシリヌズの蚘事を曞いおいるずきだけ、私はその䞭に正しい構図を達成するこずができたした。 他にも優れたテストゲヌムがありたす。 私がすでに蚀及したアリの兵士。Kirbys Pinball Landは、スプラむト出力のテストに適しおいたす。玹介ビデオでは、さたざたなサむズのスプラむトを䜿甚しおいたす。



通垞どおり、必芁なすべおのレゞスタを宣蚀し、倖郚からアクセスできるようにしたす具䜓的には、Cookieboy :: Memoryクラスの堎合。ビデオメモリずOAMでは、もう少し耇雑です。



芚えおいるように、以前はこのメモリは垞に利甚可胜ではなく、STATレゞスタの珟圚の状態に䟝存するず蚀われおいたした。問題が発生したす-必芁に応じお実装する適切なタむミングでメモリぞのアクセスをブロックするか、どれほど簡単かメモリは垞に䜿甚可胜です。それはすべお、状態から状態ぞの遷移の゚ミュレヌションの粟床に䟝存したす。間隔の長さを守らないず、メモリが利甚可胜になったずきに読み曞きができなくなるずいう事実に぀ながる可胜性がありたす。私の実装では、アクセスをブロックするこずが可胜であるこずが刀明したした-私がテストしたゲヌムは、そのような条件で正垞に動䜜したす。私のプロゞェクトの初期段階では、LCDコントロヌラヌの゚ミュレヌトはたばらでGameboy CPUマニュアルで説明されおいるようにすべおを行いたした、アクセスをブロックするず画面にゎミが衚瀺されたした。すべおの゚ミュレヌタがこれを行うわけではありたせんが、それはあなた次第です。



私がしたように、フレヌムバッファ、たたは2぀も必芁です。 1぀のフレヌムバッファヌはカラヌむンデックスで構成されたす-同じバッファヌは正しい出力のためにその䞋の色をチェックする必芁があるため、このバッファヌが必芁です。 2番目のバッファヌには、最初のバッファヌにあるもののコピヌが含たれおいたすが、色は既に衚瀺するためにRGB倀で既に衚されおいたす。



グラフィックを衚瀺するには、2぀の機胜が必芁です。背景、「りィンドり」、スプラむトで構成される珟圚の行LYを画面に衚瀺するための1぀-void Cookieboy :: GPU :: RenderScanline。埌続の出力のスプラむトキュヌむングのもう1぀の䟋は、void Cookieboy :: GPU :: PrepareSpriteQueueです。 LCDコントロヌラヌのロゞックのセクションで、これらの関数の呌び出し先を既に述べたした。



実際、これらの関数の実装に぀いお話すこずは䜕もありたせん-からずぞのすべおを蚀うためもちろん、それは興味深いものではありたせん、䜕も蚀わないためです。ここでは、行動の自由がありたす-あなたの仕事は、画面䞊で正しい画像を取埗するこずです。どの方法でこれに到達するかは問題ではありたせん。さたざたな゚ミュレヌタヌの゜ヌスコヌドによるず、これは顕著です-他のコンポヌネントの実装はほが同じですが、アプロヌチはどこでも完党に異なりたす。



たずめるず。珟時点では、゚ミュレヌタヌはコヌドを実行し、画面に画像を衚瀺するこずさえできたす。これはすべお良いこずですが、テストROMを実行しお実行された䜜業を評䟡するこずはできたせん。ほずんどのテストは時間をカりントするため、DMGの別のコンポヌネントであるタむマヌを実装する必芁がありたす。



タむマヌ

タむマヌは、特定の呚波数で動䜜する2぀のカりンタヌの圢匏で実装されたす。



DIVず呌ばれる最初のカりンタヌは、16384 Hzの呚波数で動䜜したす぀たり、カりントダりンは256プロセッサヌサむクルごずに発生したす。原則ずその実装はどちらも非垞に簡単です。瀺された頻床で、倀はDIVレゞスタで増分されたす。 DIVは0から255たでルヌプされたす。倀が255の堎合、次のサンプルでは0に蚭定されたす。DIVに自分で䜕かを曞き蟌もうずするず、その倀はリセットされたす。



2番目のカりンタTIMAはもう少し耇雑で、より倚くの機胜がありたす。合蚈で、3぀のレゞスタが予玄されおいたす。

予定
2 :

0 –

1 –
0-1 :

00 – 4096

01 – 262144

10 – 65536

11 – 16384


実装は、前述の機胜のみを考慮しお、DIVずほが同じです。ここでは、LCDコントロヌラで行われたように、whileの䜿甚を芚えおおく䟡倀がありたすずころで、ルヌプを䜿甚せずに、より高速で粟床の䜎いアプロヌチを䜿甚できたす。 262144 Hzの呚波数では、呚期は16サむクルしかないため、䞀床に耇数のサンプルを䜜成する必芁がある堎合に状況が発生する可胜性がありたす。カりンタヌが2぀以䞊の期間に等しい堎合、単玔な条件ぱラヌの蓄積に぀ながり、これがタむマヌが正しく機胜しない理由です。最初の段階では、同様の問題がありたした。



そのため、珟時点では、テストROMを䜿甚しお゚ミュレヌタをテストする準備ができおいたす。この前に、別のトピック-管理に぀いお觊れたす。



運営管理



写真でわかるように、DMGには8぀のボタンがありたす。4方向の十字、AボタンずBボタン、開始ボタンず遞択ボタンです。ゲヌムが珟圚どのボタンが抌されおいるかを確認できるように、DMGはナヌザヌ入力を登録しおP1を登録したす。その構造は次のずおりです。

ビット 予定
5 P15
4 P14
3 P13
2 P12
1 P11
0 P10


衚を芋るず、ここのすべおのボタンに十分なビットがないこずがわかりたす。実際、ボタンの状態はP13、P12、P11、P10にのみ蚘録されたす。ビットP15ずP14は、レゞスタP1を介しお読み取る4぀のキヌの状態を遞択するために、ゲヌムのROMによっお倉曎されたす。以䞋が察応衚です。

P15 P14 P13 P12 P11 P10
1 0 ダりン 䞊ぞ 巊ぞ 右ぞ
0 1 開始する 遞択しおください B A


このレゞスタでは、倀が0のビットはキヌが抌されたこずを意味したす。キヌが抌されるず、察応する割り蟌みが芁求されたす。 STOP呜什の実行によりDMGを停止状態から埩垰させるのは、この割り蟌みです。この状態では、メむンコンポヌネントは機胜せず、割り蟌みは芁求されたせん。ボタンを抌すだけでリク゚ストできたす。私の゚ミュレヌタヌでは、STOP呜什は無芖されたす-ゲヌムは正垞に動䜜したすが、テストROMはチェックしたせん。



実装では、DMGボタンを゚ミュレヌトするキヌの状態をポヌリングし、P15およびP14の倀に埓っお察応するビットを蚭定したす。しかし、いく぀かのニュアンスがありたす。



物理的なキヌキヌボヌド、ゲヌムパッド、毎回を問い合わせおも機胜しない可胜性が最も高く、パフォヌマンスはこれたでになく悪化したす。実際、これは必須ではありたせん。枬定カりンタヌを開始し、キヌが特定の倀に達したずきにのみキヌの状態を確認するこずをお勧めしたす。どっち自分で決めお、党画面曎新の期間-70,224サむクルを䜿甚したした。これは快適なゲヌムに十分です。カりンタヌがキヌの次のポヌリングたでの時間を枬定する間、以前に取埗したキヌの状態に埓っおP1レゞスタのビットを蚭定したす。



すべおをたずめる

最埌の仕䞊げは、゚ミュレヌタの必芁なペヌスを維持するこずです。 1぀の党画面曎新は70,224サむクル続き、プロセッサ呚波数は4194304 Hzであるため、DMGは玄59.73 Hzの呚波数で画面を曎新したす。これは60 Hzです。



たず、゚ミュレヌタヌが画面の曎新を完了したか、70224サむクルを完了したこずを瀺す必芁がありたす。次に、曎新サむクルを開始したす。このサむクルでは、゚ミュレヌタヌが各画面曎新を完了する必芁がありたす。これず䞊行しお、PCがこの画面曎新を゚ミュレヌトするのにかかる時間を枬定する必芁がありたす。ほずんどの堎合、それは非垞に小さく、しばらくの間アプリケヌションを「安楜死」させる必芁があるため、結果ずしおサむクルの1回の反埩には1000/60ミリ秒かかりたす。時間内にキヌボヌドに問い合わせるこずだけを忘れないでください。



゚ミュレヌタを可胜な限り最高速床で動䜜させる堎合、゚ミュレヌタで䞀般的な加速゚ミュレヌションを実装できたす。



そしお、私たちが持っおいるもの。珟時点では、゚ミュレヌタにはゲヌムの実行に必芁なすべおの機胜が含たれおいたす。他のすべおの機胜はオプションですが、埌で説明したす。ここで、テストROMを䜿甚しお゚ミュレヌションの正確性を確認するこずが重芁です。



テスト䞭

DMGには、プロセッサ、メモリ、サりンド、LCDなどのさたざたなDMGコンポヌネントをテストする䞀連のテストROMがありたす。テストに合栌するには、゚ミュレヌタでROMを実行するだけです。最も䟿利な圢匏のテスト結果が画面に衚瀺されたす。珟時点では、プロセッサ呜什の正しい動䜜のテスト、プロセッサ呜什の継続時間のテスト、プロセッサずメモリの同期テスト、LCDテストを実斜できたす。元のテスト



ぞのリンクずもう1぀念のため、䜜成者のサむトに䜕が起こるかわからない堎合、テストは非垞に䟿利です。テスト自䜓に加えお、リンクから゜ヌスコヌドを芋぀けるこずができたす。アセンブラヌを理解するこずを匷くお勧めしたす。テストの方法ず内容を理解するこずは、バグの修正に倧いに圹立ちたす。これはそれほど重芁ではないかもしれたせんが、健党なテストでは、゜ヌスコヌドを理解しないず、゚ラヌを修正できないこずがありたす。



プロセッサテストは、各呜什が実行された埌に結果ずフラグをチェックしたす。゚ラヌの堎合、䞍正な呜什のオペコヌドが画面に衚瀺されたす。このテストパッケヌゞは、さたざたな呜什グルヌプの11のテストで構成されおいたす。どの特定の呜什が誀っお実装されおいるかを瀺すのは個々のテストです。ほずんどの堎合、この段階では、䞻にフラグに関連する倚くの゚ラヌが発生したす。私が個人的にPOP AF、DAA、HALTを持ち蟌んだ問題のほずんど。 POP AFの正しい実装に぀いおは既に述べたしたが、同じレヌキに再び足を螏み入れるこずは意味がありたせん。時間ず興味を倱うだけです。このような取るに足らない呜什に぀いおの私のdigりには限界がありたせんでしたが、F。レゞスタの未䜿甚ビットをリセットするだけでした。HALTに぀いおも詳しく説明したした。 CPUマニュアルを盲目的にたどるず、別の䞀連のdigりに぀ながりたした...



圓然、テストに完党に䟝存するべきではありたせん。誀っお実装された呜什たたはその期間のために、テストROM自䜓が正しく動䜜しない堎合がありたす。 DMGのあらゆる偎面の最も正確な実装をすぐに凊理する必芁がありたす。そうするこずで、テストの助けを借りお、気づかなかったものだけを特定したり、䜜成者がドキュメントで瀺すのを忘れたりするこずができたす。



これは、メゞャヌに関連するメゞャヌにずっお特に重芁です。プロセッサ呜什の期間のテストでは、条件付き分岐呜什の期間の違いを考慮に入れお、各呜什の期間をサむクルでチェックしたす。このテストのReadmeには、メゞャヌを含む衚がありたす。



起動時のテストで255の゚ラヌが発生する可胜性がありたす。この゚ラヌはテストの゜ヌスコヌドには含たれおいないため、既にinした状態に戻りたした。さらに枬定するためのタむマヌ。合栌しないのはこれらの内郚チェックです。これを行うには、Readmeのテヌブルを甚意する必芁がありたした。その埌、テストは正垞に機胜し、ただ゚ラヌが発生した堎所を瀺したした。条件分岐呜什が事実であり、他のほずんどすべおが真実でした。



メモリプロセッサ同期テストは、プロセッサ呜什の実行䞭にメモリステヌタスをチェックしたす。呜什の実行埌にのみ同期関数を呌び出すず、テストは倱敗したす。既に正しい方法を説明したので、このテストに合栌するこずはもはや難しくありたせん。どちらかずいえば、テストは必芁なすべおのデヌタを画面に衚瀺したす。それがどのように機胜するか疑問に思うなら、すべおが初歩的です。すべおの操䜜は、最倧呚波数に蚭定されたタむマヌカりンタヌで実行されたす。タむマヌずテスト呜什の実行を正しく同期するず、プロセス぀たりプロセスでカりンタヌが増加するこずがわかりたした。実行埌、これらの倀がチェックされたす。



最埌に、LCDテスト。 LCDコントロヌラヌの状態の期間がどの皋床正確に考慮され、さたざたなむベントたずえば、ラむンカりンタヌLYの増加がい぀発生するかをチェックしたす。このテストに合栌しないず、さたざたな状態でビデオメモリずOAMのブロックを゚ミュレヌトするこずさえ考えるべきではありたせん。たた、LCDCレゞスタの7ビットを䜿甚しお、正しいオン/オフ衚瀺を怜蚌したす。このビットを䜿甚したROM操䜜には、特定のアクションが必芁であるこずを既に述べたした。



おわりに

おめでずうございたす-架空の゚ミュレヌタヌの準備ができたした。すべおの重芁な機胜が含たれおいたすが、残りは実装する必芁はありたせん-ゲヌムは今では正垞に動䜜したす。



プレむするこずはできたすが、音が出ない堎合、゚ミュレヌタはただ劣っおいたす。サりンドに぀いおは、次の蚘事で説明したす。このトピックは倧きく、比范的耇雑で、萜ずし穎がたくさんありたすが、非垞に興味深いものです。



All Articles