Графические карты обычно содержат несколько килобайт или мегабайт памяти, в которых хранятся цвета отдельных пикселей, которые затем отображаются на экране. Карта сканирует эту память несколько раз в секунду, превращая числовое представление цветов пикселей в видеосигналы (аналоговые или цифровые), которые дисплей понимает и визуализирует.
ЦПУ имеет доступ к этой памяти, и всякий раз, когда она изменяет ее, карта в конечном итоге преобразует новые данные о цвете в соответствующие видеосигналы, и на дисплее отображается обновленное изображение. Карта выполняет всю обработку асинхронно и не требует особой помощи от процессора. С точки зрения процессора это почти то же самое, что записать новый цвет пикселя в память графической карты в месте, соответствующем координатам пикселя, и забыть об этом. В действительности это может быть немного сложнее (из-за плохих артефактов синхронизации, таких как 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
или на голом компьютере x86 без какой-либо ОС, если вы загружаете свой код с помощью BIOS компьютера и ограничивает его использованием только служебных функций BIOS (прерываний) и прямого аппаратного обеспечения. доступ для всех других устройств ПК.
Кстати, вам, вероятно, будет очень легко реализовать ваш эмулятор как программу DOS и запускать его либо непосредственно в Windows XP
(Vista и 7 имеют крайне ограниченную поддержку приложений DOS в 32-разрядных выпусках и ни одной в 64-разрядных редакции, однако вы можете установить XP Mode , который является XP на виртуальной машине в 7) или, что еще лучше, в DOSBox , который, по-видимому, доступен для нескольких ОС.
Если вы реализуете это как программу Windows, вам придется использовать либо GDI
, либо DirectX
, чтобы нарисовать что-то на экране. Если я не ошибаюсь, ни один из этих двух вариантов не позволяет напрямую обращаться к памяти физической карты, так что изменения в ней будут автоматически отображаться.
Рисование отдельных пикселей на экране с использованием GDI или DirectX может быть дорогостоящим, если много рендеринга. Перерисовка всех пикселей моделируемой карты каждый раз, когда один из них изменяется, приводит к одной и той же проблеме производительности. Наилучшим решением, вероятно, является обновление экрана 25-50 раз в секунду и обновление только тех частей, которые изменились с момента последней перерисовки. Разделите буфер моделируемой карты на более мелкие буферы, представляющие собой прямоугольные области, скажем, размером 64x64 пикселя, помечайте эти буферы как «грязные» всякий раз, когда эмулятор записывает в них, и помечайте их как «чистые», когда они отображаются на экране. Вы можете настроить периодические перерисовки экрана управления таймером и выполнять их в отдельном потоке. Вы должны быть в состоянии сделать что-то похожее в Linux, но я не очень разбираюсь в графическом программировании.