Assembler - язык неограниченных возможностей


Вывод на экран через линейный кадровый буфер - часть 2


; поместить наш дескриптор в LDT и получить селектор mov ex,1 ; получить один новый дескриптор mov ах,0 ; у DPMI int 31h jc DPMI_error mov word ptr videosel,ax ; записать его селектор push ds pop es mov edi,offset videodsc ; ES:EDI - адрес нашего дескриптора mov bx,ax ; BX - выданный нам селектор mov ax,0Ch ; функция DPMI 0Ch int 31h ; загрузить дескриптор в LDT jc DPMI_error ; теперь в videosel лежит селектор на LFB ; переключение в режим 4101h (101h + LFB) mov word ptr v86_eax,4F02h ; 4F02h - установить SVGA-режим mov word ptr v86_ebx,4101h ; режим 4101h = 101h + LFB mov edi,offset v86_regs ; ES:EDI - структура v86_regs mov ах,0300h ; функция DPMI 300h mov bx,0010h ; эмуляция прерывания 10h xor ecx,ecx int 31h

mov ax,word ptr videosel ; AX - наш селектор enter_flame: ; сюда придет управление с селектором ; в ах на A000h:0000, если произошла ; ошибка в любой VBE-функции mov es,ax ; ES - селектор видеопамяти или LFB

; отсюда начинается процедура генерации пламени

; генерация палитры для пламени xor edi,edi ; начать писать палитру с адреса ES:0000 xor есх,есх palette_gen: xor еах,еах ; цвета начинаются с 0, 0, 0 mov cl,63 ; число значений для одной компоненты palette_11: stosb ; записать байт inc eax ; увеличить компоненту cmpsw ; пропустить два байта loop palette_11 ; и так 64 раза

push edi mov cl,192 palette_12: stosw ; записать два байта inc di ; и пропустить один loop palette_12 ; и так 192 раза (до конца палитры) pop edi ; восстановить EDI inc di jns palette_gen

; палитра сгенерирована, записать ее в регистры VGA DAC (см. главу 5.10.4) mov al,0 ; начать с регистра 0 mov dx,03C8h ; индексный регистр на запись out dx,al push es push ds ; поменять местами ES и DS pop es pop ds xor esi,esi mov ecx,256*3 ; писать все 256 регистров mov edx,03C9h ; в порт данных VGA DAC rep outsb push es push ds ; поменять местами ES и DS pop es pop ds

; основной цикл - анимация пламени, пока не будет нажата любая клавиша, xor edx,edx ; должен быть равен нулю mov ebp,7777h ; любое число mov ecx,dword ptr scr_width ; ширина экрана main_loop: push es ; сохранить ES push ds pop es ; ES = DS - мы работаем только с буфером ; анимация пламени (классический алгоритм) inc ecx mov edi,offset buffer mov ebx,dword ptr scr_height shr ebx,1 dec ebx mov esi,scr_width animate_flame: mov ax,[edi+esi*2-1] ; вычислить среднее значение цвета add al,ah ; в данной точке (EDI) из значений setc ah ; цвета в точке слева и на две строки mov dl,[edi+esi*2+1] ; вниз, справа и на две строки вниз add ax,dx mov dl,[edi+esi*4] ; и на четыре строки вниз. add ax,dx ; причем первое значение shr ax,2 ; модифицировать jz already_zero ; уменьшить яркость цвета dec ax already_zero: stosb ; записать новый цвет в буфер add eax,edx shr eax,1 mov byte ptr [edi+esi-1],al loop animate_flame mov ecx,esi add edi,ecx dec ebx jnz animate_flame




Начало  Назад  Вперед