グラフィックカードは通常、画面に表示される個々のピクセルの色を保存する数KBまたはMBのメモリを搭載しています。カードはこのメモリを 1 秒間に何回もスキャンし、ピクセルの色の数値表現をビデオ信号 (アナログまたはデジタル) に変換し、ディスプレイが認識して視覚化します。
CPU はこのメモリにアクセスでき、メモリが変更されるたびに、カードは最終的に新しいカラー データを適切なビデオ信号に変換し、ディスプレイには更新された画像が表示されます。カードはすべての処理を非同期で行い、CPU からの支援をあまり必要としません。CPU の観点からは、ピクセルの座標に対応する位置にあるグラフィック カードのメモリに新しいピクセルの色を書き込んで忘れてしまうようなものです。実際にはもう少し複雑かもしれません ( などの不十分な同期アーティファクトtearingのためsnow) が、それが要点です。
グラフィック カードをシミュレートする場合、シミュレートされたカードのメモリを物理グラフィック カードのメモリにミラーリングする必要があります。OS で物理グラフィック カードのメモリに直接アクセスできる場合、それは簡単な作業です。エミュレートされたコンピューターのメモリへの書き込みを次のように実装するだけです。
void MemoryWrite(unsigned long Address, unsigned char Value)
{
if ((Address >= SimulatedCardVideoMemoryStart) &&
(Address - SimulatedCardVideoMemoryStart < SimulatedCardVideoMemorySize))
{
PhysicalCard[Address - SimulatedCardVideoMemoryStart] = Value;
}
EmulatedComputerMemory[Address] = Value;
}
もちろん、上記は、シミュレートされたカードが物理カードとまったく同じ解像度 (たとえば、1024x768) とピクセル表現 (たとえば、ピクセルあたり 3 バイト、赤の最初のバイト、緑の 2 番目のバイト、青の 3 番目のバイト) を持っていることを前提としています。実生活では、もう少し複雑になる可能性がありますが、これが一般的な考え方です。
MSDOSPC BIOS によってコードをブート可能にし、BIOS サービス機能 (割り込み) のみを使用するように制限し、他のすべての PC にハードウェアへの直接アクセスを制限すると、OS を使用せずにベア x86 PC内またはベア x86 PC 上で物理カードのメモリに直接アクセスできます。デバイス。
ところで、エミュレーターを DOS プログラムとして実装し、それを直接実行するのはおそらく非常に簡単ですWindows XP(Vista と 7 では、32 ビット版では DOS アプリのサポートが非常に制限されており、64 ビット版ではサポートされていません。ただし、 、XP Modeをインストールします。これは 7) の VM に XP をインストールします。
ものを Windows プログラムとして実装する場合、画面に何かを描画するためにGDIまたはを使用する必要があります。DirectX私が間違っていない限り、これら 2 つのオプションのどちらも、物理カードのメモリに直接アクセスして、その変更が自動的に表示されるようにすることはできません。
レンダリングが多い場合、GDI または DirectX を使用して画面上に個々のピクセルを描画すると、負荷が高くなる可能性があります。シミュレートされたカードのピクセルのいずれかが変更されるたびにすべてのピクセルを再描画すると、同じパフォーマンスの問題が発生します。最良の解決策は、おそらく 1 秒間に 25 ~ 50 回画面を更新し、最後の再描画以降に変更された部分のみを更新することです。シミュレートされたカードのバッファーを、たとえば 64x64 ピクセルの長方形の領域を表す小さなバッファーに分割し、エミュレーターがそれらに書き込むたびにこれらのバッファーを「ダーティ」としてマークし、画面に描画されたときに「クリーン」としてマークします。画面の再描画を駆動する定期的なタイマーを設定し、それらを別のスレッドで実行できます。Linux でもこれと同様のことができるはずですが、Linux でのグラフィックス プログラミングについてはよくわかりません。