显卡通常带有许多 KB 或 MB 的内存,用于存储单个像素的颜色,然后显示在屏幕上。该卡每秒多次扫描此内存,将像素颜色的数字表示转换为显示器可以理解和可视化的视频信号(模拟或数字)。
CPU 可以访问此内存,并且无论何时更改它,卡最终都会将新的颜色数据转换为适当的视频信号,并且显示器会显示更新的图像。该卡异步执行所有处理,不需要 CPU 的太多帮助。从 CPU 的角度来看,这很像将新的像素颜色写入显卡内存中与像素坐标相对应的位置,然后忘记它。它在现实中可能会稍微复杂一些(由于同步工件,如tearing
等snow
),但这就是它的要点。
模拟显卡时,需要以某种方式将模拟卡的内存镜像到物理显卡的内存中。如果在操作系统中您可以直接访问物理图形卡的内存,这是一件容易的事。简单地实现写入模拟计算机的内存,如下所示:
void MemoryWrite(unsigned long Address, unsigned char Value)
{
if ((Address >= SimulatedCardVideoMemoryStart) &&
(Address - SimulatedCardVideoMemoryStart < SimulatedCardVideoMemorySize))
{
PhysicalCard[Address - SimulatedCardVideoMemoryStart] = Value;
}
EmulatedComputerMemory[Address] = Value;
}
当然,以上假设模拟卡具有与物理卡完全相同的分辨率(例如,1024x768)和像素表示(例如,每个像素 3 个字节,第一个字节为红色,第二个为绿色,第三个为蓝色)。在现实生活中,事情可能会稍微复杂一些,但同样,这是一般的想法。
MSDOS
如果您使您的代码可通过 PC BIOS 引导并将其限制为仅使用 BIOS 服务功能(中断)和对所有其他 PC 的直接硬件访问,则您可以直接在裸 x86 PC 中或在没有任何操作系统的情况下访问物理卡的内存设备。
顺便说一句,将您的模拟器实现为 DOS 程序并直接在其中运行它可能会非常容易Windows XP
(Vista 和 7 对 32 位版本的 DOS 应用程序的支持极其有限,而在 64 位版本中则没有;但是您可以,安装XP Mode,这是 7 中 VM 中的 XP)或更好的DOSBox之类的东西,它似乎可用于多个操作系统。
如果您将事物实现为 Windows 程序,则必须使用GDI
或DirectX
才能在屏幕上绘制某些东西。除非我弄错了,否则这两个选项都不允许您直接访问物理卡的内存,以便自动显示其中的更改。
如果有大量渲染,使用 GDI 或 DirectX 在屏幕上绘制单个像素可能会很昂贵。每次当其中一个被更改时重新绘制所有模拟卡片的像素都会导致相同的性能问题。最好的解决方案可能是每秒更新屏幕 25-50 次,并且只更新自上次重绘以来发生变化的部分。将模拟卡的缓冲区细分为较小的缓冲区,表示例如 64x64 像素的矩形区域,每当模拟器写入它们时将这些缓冲区标记为“脏”,当它们在屏幕上绘制时将它们标记为“干净”。您可以设置一个周期性的计时器来驱动屏幕重绘并在单独的线程中进行。你应该能够在 Linux 中做类似的事情,但我对那里的图形编程知之甚少。