2017-07-25 18 views
1

私は最初のNESエミュレータをC言語で書いています。目標は、通常のゲームでゲームをプレイするためには、理解しやすく正確なサイクルを作ることですハードウェアの速度。 6502のテクニカルリファレンスを掘り下げると、命令が複数のCPUサイクルを消費するように思えます。また、特定の条件(分岐など)に応じてサイクルも異なります。私の計画は、読み取りと書き込みの機能を作成し、switchを使用してモードをアドレッシングすることによってオペコードをグループ化することです。命令あたり6502サイクルのタイミング

質問です:私は、このようなBRKなど、複数サイクルの命令を、持っているとき、私は正確に各サイクルで何が起こっているかをエミュレートする必要があります:

#Method 1 

cycle - action 

1 - read BRK opcode 
2 - read padding byte (ignored) 
3 - store high byte of PC 
4 - store low byte of PC 
5 - store status flags with B flag set 
6 - low byte of target address 
7 - high byte of target address 

...または私は実行することができますすべての必要な操作を1つの「サイクル」(1つのswitchcase)に置き換え、残りのサイクルで何もしないでください。

#Method 2 

1 - read BRK opcode, 
read padding byte (ignored), 
store high byte of PC, 
store low byte of PC, 
store status flags with B flag set, 
low byte of target address, 
high byte of target address 
2 - do nothing 
3 - do nothing 
4 - do nothing 
5 - do nothing 
6 - do nothing 
7 - do nothing 

どちらの方法も望ましい7サイクルを消費するため、2つの方法に違いはありませんか? (精度的に)

個人的に私は(助けてください!)

+1

CPUをエミュレートするだけで**違いはありません。しかし、たとえばSTA命令と同じメモリにアクセスするペリフェラルについて考えると、メモリセルが正確に変化したときに重要になるかもしれません。したがって、オプション1に行く。 –

+1

どのように、あなたは状態マシンが必要でしょうか? –

+0

方法1を実装している良いCの例やソースを知っていますか?私が見つけることができるのは、非Cエミュレータであり、現在のレベルでは理解できないものもあります( –

答えて

4

はあなたを行います...しかし、私はそれを実装するために適切な、簡単な方法を考えることはできません、方法1が邪魔-to-Goの解決策だと思います'必要性'は?それはソフトウェアによって異なります。最も単純な例を考えてみましょう。

STA ($56), Y 

...ハードウェアレジスタにヒットすることがあります。正しいサイクルで少なくとも書き込みをしないと、タイミングの不足が生じています。書き込み先のレジスタに間違った時刻に書き込まれます。もしそれがパレットレジスタのようなもので、プログラマがラスタ効果を実行しているなら、どうでしょうか?それで色が変わる場所をちょうど移動しました。あなたはグラフィック出力を変更しました。

実際には、賢いプログラマーはそれよりずっとスマートなことをします。正確なサイクルでハードウェア値を読み込み、変更してから、別の正確なサイクルで書き戻すために、リード・モディファイ・ライト・オペレーションを使用することができます。

は、だから私の答えは:

  1. との差が、(1)及び(2)任意の効果を持つことになりますように、ほとんどのソフトウェアが書かれていません。しかし、
  2. 確かに、著者は非常に賢いだったので、
  3. 確かに、著者が原因を認識しているかどうかに関わらず、クールな効果が見られるまで実験したからです。どのような場合でも、エミュレータで正しく動作しないものが見つかった場合、すべての順列と潜在的な原因の組み合わせを考慮してどれくらいの時間を費やしたいですか?あなたが取り除くことができるすべては、考慮する必要が少ないものです。

ほとんどのエミュレータは、(2)の方法を使用していました。通常は、ソフトウェアの90%で動作します。それから、エミュレータの作者が特別な場合に特別なケースを置く、動作しないケースがいくつかあります。それらは通常、相互作用が不十分になり、エミュレータは誰かがより良いものを書くまで、利用可能なソフトウェアの異なる95%の組み合わせをサポートする間、残りの人生を振動させました。

したがって、方法(1)を使用してください。そうでなければそうでないと壊れてしまうソフトウェアが発生します。また、より多くのことを教えてくれるでしょうし、特別なケースの潜在的な動機を排除するので、コードをきれいに保ちます。それは少し遅くなるだろうが、私はあなたのコンピュータがおそらくそれを処理できると思う。

その他のヒント:6502にはいくつかのアドレッシングモードがあり、アドレッシングモードはタイミングを完全に指示します。 This documentは完璧なタイミングを知るために必要なすべてです。完璧な清潔さが必要な場合は、スイッチテーブルでアドレッシングモードと中央操作を選択してから終了し、アドレッシングモードで分岐してメインアクションを実行することができます。

バニラreadwriteの方法を使用する場合は、6502のスマートな方法は、すべての単一サイクルが読み取りまたは書き込みのいずれかであるため、ほとんどあなたが言う必要があります。メソッドシグネチャに注意してください。例えば、6502にはSYNCピンがあり、観察者がオペコードの読み取りから通常の読み取りを区別することができます。暗黙のページングのためにそれを公開しているシステムでよく使用されるNESがカートリッジにそれを公開するかどうかを調べ、NESの主要な識別特性は何百ものページングスキームがあるということです。

EDIT:マイナーアップデート:

  • それは6502が常に読み取りまたは書き込みを行うと言うことは、実際に完全に真実ではありません。 RDY入力もあります。 RDY入力がアサートされ、6502が読もうとする場合、意図された読出しアドレスを維持しながら停止する。 6502はRDY入力に関係なく書き込みを行いますが、これは本当にシングルステッピングを助けることを意味しています.NES cartridge pinoutには一見含​​まれていないようですが、実際にはほとんど使用されません。そのマシン用に実装する必要はありません。
  • 同じピン配列では、同期信号もそのシステムのカートリッジには露出していないようです。
+0

ニースのTommy。あなたは、私がタイプするにはあまりにも疲れていたものを正確に言った。しばらくの間、マイクロコード6502を書こうと思っていました。@ H.JJang:単純な方法は、スイッチ(オペコード)の各オペコードのスイッチ(サイクル)ステートメントになります。もう1つの方法は、マイクロコードテーブル(あなたの方法#1)を書くことです。 Tommyの説明によれば、各アドレッシングモードは実際のオペコード操作を除いて同じシーケンスを持ちます。 –

+0

@NickWestgate現在の6502エミュレーションはマイクロコード化されています!マイクロコードは、事前に準備されていないので、私は一緒に行ったので、理想的ではありませんでした。私は以来、Z80をマイクロコードしました。私はそれをはるかに体系的に扱っていました。 '90年代からの私の6502エミュレーションの進化:正確なサイクルではなく、(1)関数ポインタのテーブル。 (2)1つの大きなスイッチのステートメントは、指示にスイッチ、正確なサイクルが、命令の完全な数だけを実行することができますので、時間マスターでなければなりません。 (3)1つの大きなスイッチステートメント、スイッチオン命令、別のスレッド、必要なときにブロックして任意のサイクル数実行する。 (4)マイクロコード化されている。 – Tommy

+0

この回答は私のコメントで表現しようとしたものの良い説明を提供します。 –

関連する問題