PDA

Просмотр полной версии : Вопрос по эмулятору (самодельному)



Zarax
18.07.2010, 16:39
для того чтобы освежить в памяти ассемблер Z80, решил напистать эмулятор с нуля (намеренно чтобы не поддаваться искушению подглядывать в чужие исходники, оставил себе под рукой только книжку по микропроцессору да статьи с журналов Радио, правда когда дело дошло до загрузки снапшотов, разок всё-таки заглянул)...сейчас он уже делает вид что работает, правда я что-то перемудрил с формированием строки для вывода на экран, из-за чего изображение выводится не вполне корректно. но вопрос заключается в другом. Для вывода на экран я использую функции GDI - заполняю построчно предварительно создаый битмап через SetDIBits потом копирую его на контекст. Всё работает но как-то медленно, пробовал заполнять непосредственно контекст с помощью SetDIBitsToDevice там тормоза ещё больше, скажите вобще реально ли написать нормальный вывод на экран используя только GDI ? Может есть какие нибудь примеры реализации?

Z80Stealth
18.07.2010, 19:15
Встречный вопрос - зачем вообще рисовать через GDI?

Alexandr Medvedev
18.07.2010, 23:28
реально ли написать нормальный вывод на экран используя только GDI ?UnrealSpeccy среди прочего может и через GDI картинку выводить и при этом считается одним из самых быстрых эмулей. Исходный тест UnrealSpeccy открыт.

ARTi
19.07.2010, 19:07
я использую функции GDI - заполняю построчно предварительно создаый битмап через SetDIBits
Дурацкий вопрос - а битмап создается с помощью CreateDIBSection? Если нет, тогда проблема скорости вполне закономерна: при каждой модификации посредством SetDIBits системе надо из DDB сделать временный DIB (естественно не без копирования), на этом временном DIB-е проделать изменения, а потом вернуть все взад - преобразовать и скопировать из DIB в DDB, после чего удалить DIB.

---------- Post added at 18:52 ---------- Previous post was at 18:22 ----------

Короче, я понял - скорее всего битмап создается именно через CreateCompatibleBitmap, что и порождает дальнейшие тормоза с SetDIBits.
Вот пример кода:


void CBaseView::OnDraw(CDC* pDC)
{
CRect rc;
GetClientRect(&rc);

CDC dc2, *pMemDC;
CBitmap *pBmpPrev = NULL;
void *pBuf = NULL;
int width = rc.Width();
int height = rc.Height();

if(dc2.CreateCompatibleDC(pDC))
pMemDC = &dc2;
else
pMemDC = pDC;

BITMAPINFO bmp_info;
bmp_info.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
bmp_info.bmiHeader.biWidth = width;
bmp_info.bmiHeader.biHeight = height;
bmp_info.bmiHeader.biPlanes = 1;
bmp_info.bmiHeader.biBitCount = 32;
bmp_info.bmiHeader.biCompression = BI_RGB;
bmp_info.bmiHeader.biSizeImage = 0;
bmp_info.bmiHeader.biXPelsPerMeter = 0;
bmp_info.bmiHeader.biYPelsPerMeter = 0;
bmp_info.bmiHeader.biClrUsed = 0;
bmp_info.bmiHeader.biClrImportant = 0;

CBitmap *pBitmap = CBitmap::FromHandle(
CreateDIBSection(m_pDC->m_hDC,
&bmp_info,
DIB_RGB_COLORS,
&pBuf,
0,
0));
pBmpPrev = m_pDC->SelectObject(pBitmap);

//
// painting here on pMemDC...
// ...or u can paint directly in bitmap buffer pBuf
//

PaintData(pMemDC);

if(pDC != pMemDC)
{
pDC->BitBlt(0, 0, width, height, pMemDC, 0, 0, SRCCOPY);
pMemDC->DeleteDC();
}
else
pMemDC->SelectObject(pBmpPrev);

if(pBitmap)
pBitmap->DeleteObject();
}

Как видно из приведенного фрагмента и каментов, можно напрямую менять буфер по указателю pBuf, ибо он имеет простой формат BI_RGB (по конкретике в MSDN). Т.е. копирование в лице чего-либо, в том числе и SetDIBits, вообще не нужно, ибо можно заниматься формированием кадра ZX Spectrum прямо в pBuf.

---------- Post added at 19:07 ---------- Previous post was at 18:52 ----------

И еще добавлю от себя. Вопрос "зачем вообще рисовать через GDI", в случае, когда тема звучит примерно как "медленный вывод в GDI, помогите", неуместен. На вопрос же

реально ли написать нормальный вывод на экран используя только GDI?
отвечу вкратце, что сделать нормальный вывод, используя GDI, вполне реально, особенно, используя библиотеки навроде AGG; однако, если нужно использовать аппаратное ускорение 3D видеоадаптера, тут GDI отдыхает по сравнению со, скажем, OpenGL (не эмулируемым конечно же). Также, у вышеприведенного наброска метода рисования в памяти есть и другие недостатки - отсутствие какого-либо ускорения 2D и удобств, каковые имеются, к примеру, в DirectX. На мой взгляд, для эмуляции экрана ZX Spectrum, если не нужно сглаживание, эмуляция нерезкого изображения, ТВ- и прочие эффекты, GDI подойдет в самый раз. Если потенциально нужна кроссплатформенность - тогда наоборот, лучше сразу забыть про GDI.

rasmer
27.08.2010, 21:14
ну чо - как резалты эмулелепительства?