, на этот раз в виде газовой горелки. Древнючий мой исходник лета 2000-го, код без комментариев. Но так даже полезней-интересней, т.к. все стандартно и описано в интернетах, так что придется немного погуглить. Компилировать: tasm /m2 phire.asm tlink /t phire.obj Код (ASM): model tiny codeseg org 0100h @strt: ; vmode mov ax,0013h int 10h mov ax,0a000h mov ds,ax mov cx,0040h ; pal @lc00: dec cx mov dx,03c8h mov al,cl out dx,al inc dx mov al,00h out dx,al out dx,al mov al,cl out dx,al dec dx mov al,cl add al,40h out dx,al inc dx mov al,cl out dx,al out dx,al mov al,3fh out dx,al inc cx loop @lc00 ; patrn @lc01: mov di,0f8c0h mov cx,0140h in ax,40h push di ;; @lc02: dec cx rol ax,01h add ah,al push ax ;; shr al,01h cmp al,20h jb @lc06 mov [di],al @lc06: pop ax ;; inc di inc cx loop @lc02 pop di ;; mov cx,0040h ; blurrr @lc03: push cx ;; mov cx,0140h @lc04: dec cx mov ax,[di] add al,ah shr al,01h jz @lc05 dec al @lc05: push di sbb di,013fh mov [di],al pop di mov [di+01h],al inc di inc cx loop @lc04 sub di,0280h pop cx ;; loop @lc03 ; esc in al,60h dec al jnz @lc01 mov ax,0003h int 10h retn end @strt Во вложении скомпилированный COM.
Немного теорииВ сущности, пламя, это тот же эффект Blur, изменений совсем немного. Допустим, мы хотим изобразить самый простой вариант: Пламя поднимается снизу экрана и постепенно гаснет. Наша формула true-blur`а изменится совсем чуть-чуть: Код (C): buffer[x][y+1]=(screen[x-1][y+1]+screen[x-1][y]+ screen[x-1][y-1]+screen[x][y+1]+ screen[x][y-1]+screen[x+1][y+1]+ screen[x+1][y]+screen[x+1][y-1])/8; Для того, чтобы пламя красиво гасло, установим палитру так: Номер цвета064128192255Цветчерный[math]\to[/math]красный[math]\to[/math]желтый[math]\to[/math]ярко-желтый[math]\to[/math]белыйПример: Код (C): for(short k=0;k<=63;k++) { setrgbpalette(k,k,0,0); setrgbpalette(k+64,63,k,0); setrgbpalette(k+128,63,63,k); setrgbpalette(k+192,63,63,63); } Если вам кажется, что пламя слишком медленно гаснет, то формулу можно переписать вот так: Код (C): short color=(screen[x-1][y+1]+screen[x-1][y]+ screen[x-1][y-1]+screen[x][y+1]+ screen[x][y-1]+screen[x+1][y+1]+ screen[x+1][y]+screen[x+1][y-1])/8; if(color>number) color-=number; else color=0; buffer[x][y+1]=color; Значение number выберите по своему вкусу, чем оно больше, тем быстрее будет гаснуть пламя.Да, и самое главное, чтобы пламя "горело", его надо постоянно "подпитывать": в самую нижнюю строчку в начале каждого кадра записывать пиксели со случайным цветом.Добавится вот такая строка: Код (C): for(x=0;x<320;x+=4) { char color=rand()%256; screen[x][199]=c; screen[x+1][199]=c; screen[x+2][199]=c; screen[x+3][199]=c; } Забивая сразу четыре пикселя случайным цветом, мы получаем более красивое пламя. Естественно, эту и несколько следующих строк на экран мы не выводим. Почему? Догадайтесь сами! Опять же, для ускорения можно использовать вариант блюра с четырьмя усредняемыми пикселями, немного его изменив: Код (C): screen[x][y]=(screen[x-1][y-1]+screen[x][y-1]+ screen[x][y-1]+screen[x+1][y-2])/4; Вот еще одна быстрая формула: Код (C): for(short y=0;y<197;y+=2) for(short x=1;x<319;x++) { short high=screen[x-1][y-2]+screen[x][y-2]+screen[x+1][y-2]; char low=screen[x][y-4]; char pixel=(high+low)/4; screen[x][y]=pixel; screen[x][y-1]=(pixel+low)/2 } Взято здесь, текст программы немного переделан, в результате СОМ-файл уменьшился с 693 байт до 583 байт Код (ASM): ; masm dos com # .model tiny .code .386 org 100h VGA_SEGMENT equ 0A000h IMPUT_STATUS_0 equ 3DAh ;регистр статуса ввода 0 WIDTH_SCREEN equ 320 HEIGHT_SCREEN equ 200 SCREENSIZE equ WIDTH_SCREEN*HEIGHT_SCREEN MEMBLOCKSIZE equ SCREENSIZE/16 screen equ word ptr [bp-2] temp1 equ word ptr [bp-4] temp2 equ word ptr [bp-6] start: mov sp, 0BC0h mov ah, 4Ah; ADJUST MEMORY BLOCK SIZE (SETBLOCK) mov bx, 0BCh; ES = segment address of block to change int 21h; BX = new size in paragraphs enter 6,0 ;RANDOMIZE push 0 pop es ;получаем системное время, накапливаемое в 4-х байтовой ячейке с адресом 46Ch mov ax, es:[46Ch] mov temp1, ax mov ax, es:[46Eh] mov temp2, ax mov ax, 13h int 10h ;setcolortable mov cx,63 @@: push cx push cx push 0 push 0 call setrgbpalette mov al, cl add al, 64 push ax push 63 push cx push 0 call setrgbpalette mov al, cl add al, 128 push ax push 63 push 63 push cx call setrgbpalette mov al, cl add al,192 push ax push 63 push 63 push 63 call setrgbpalette dec cx jns @b ;setcolortable mov bx, MEMBLOCKSIZE mov ah, 48h; ALLOCATE MEMORY int 21h; BX = number of 16-byte paragraphs desired mov screen, ax ;clearblock mov es, ax xor eax, eax xor di, di mov cx,SCREENSIZE/4 rep stosd mov bx, MEMBLOCKSIZE mov ah, 48h; ALLOCATE MEMORY int 21h; BX = number of 16-byte paragraphs desired mov fs,ax;buffer ;clearblock mov es, ax xor eax, eax xor di, di mov cx,SCREENSIZE/4 rep stosd loc_10143: xor ax, ax mov es, ax mov ax, es:[41Ah] sub ax, es:[41Ch] jnz loc_10158;нажали на клавиатуру? call incfire ;trueflamescreen mov di,WIDTH_SCREEN xor si, si mov dx,HEIGHT_SCREEN-2 loc_10218: mov bx,13Fh loc_10220: movzx ax, byte ptr es:[di-WIDTH_SCREEN-1] movzx cx, byte ptr es:[di-WIDTH_SCREEN] add ax, cx movzx cx, byte ptr es:[di-WIDTH_SCREEN+1] add ax, cx movzx cx, byte ptr es:[di-1] add ax, cx movzx cx, byte ptr es:[di+1] add ax, cx movzx cx, byte ptr es:[di+WIDTH_SCREEN-1] add ax, cx movzx cx, byte ptr es:[di+WIDTH_SCREEN] add ax, cx movzx cx, byte ptr es:[di+WIDTH_SCREEN+1] add ax, cx shr ax, 3 test al,al je @f dec al @@: mov fs:[si], al inc di inc si dec bx jns loc_10220 dec dx jnz loc_10218 ;copybufferscreen push ds push fs pop ds;buffer xor si, si xor di, di mov cx,SCREENSIZE/4 rep movsd pop ds call copyvirtualscreen jmp loc_10143 loc_10158: mov ah, 0 int 16h ; KEYBOARD - READ CHAR FROM BUFFER, WAIT IF EMPTY loc_1015C: xor ax, ax mov es, ax mov ax, es:[41Ah] sub ax, es:[41Ch] jnz loc_1016E call incfire ;fastflamescreen xor di, di mov si, HEIGHT_SCREEN-4 loc_102B7: mov bx, WIDTH_SCREEN-1 loc_102BF: movzx ax, byte ptr es:[di+WIDTH_SCREEN-1] movzx cx, byte ptr es:[di+WIDTH_SCREEN] add ax, cx movzx cx, byte ptr es:[di+WIDTH_SCREEN+1] add ax, cx movzx cx, byte ptr es:[di+WIDTH_SCREEN*2] add ax, cx shr ax, 2 test al,al je @f dec al @@: stosb dec bx jns loc_102BF dec si jns loc_102B7 call copyvirtualscreen jmp short loc_1015C loc_1016E: mov ah, 0 int 16h ; KEYBOARD - READ CHAR FROM BUFFER, WAIT IF EMPTY loc_10172: xor ax, ax mov es, ax mov ax, es:[41Ah] sub ax, es:[41Ch] jnz short loc_10184 call incfire ;fastestflamescreen xor di, di mov bx, HEIGHT_SCREEN-4 loc_10300: mov si, WIDTH_SCREEN-1 loc_10308: movzx ax, byte ptr es:[di+WIDTH_SCREEN*2-1] movzx cx, byte ptr es:[di+WIDTH_SCREEN*2] add ax, cx movzx cx, byte ptr es:[di+WIDTH_SCREEN*2+1] add ax, cx xchg ax, dx movzx cx, byte ptr es:[di+WIDTH_SCREEN*4] mov ax, cx add ax, dx shr ax, 2 cmp al, 2 jbe short loc_1033A sub al, 2 jmp short loc_1033C loc_1033A: mov al, 0 loc_1033C: stosb cbw mov ch,0 add ax, cx sar ax, 1 mov es:[di+WIDTH_SCREEN-1], al dec si jns loc_10308 add di,WIDTH_SCREEN sub bx,2 jns loc_10300 ;fastestflamescreen call copyvirtualscreen jmp short loc_10172 loc_10184: mov ax, 3 int 10h ; - VIDEO - SET VIDEO MODE mov ah, 0 int 16h ; KEYBOARD - READ CHAR FROM BUFFER, WAIT IF EMPTY int 20h setrgbpalette proc near blue equ byte ptr [bp+4] green equ byte ptr [bp+6] red equ byte ptr [bp+8] color equ byte ptr [bp+10] push bp mov bp, sp mov dx, 3C8h mov al, color mov ah, red out dx, ax inc dx mov al, green out dx, al mov al, blue out dx, al pop bp retn 8 setrgbpalette endp incfire proc mov es, screen mov di,WIDTH_SCREEN*(HEIGHT_SCREEN-2) mov cx,80 @@: mov ax, temp2 mov dx, temp1 shld ax,dx,8 shl dx,8 rcr ax, 1 rcr dx, 1 add temp1, dx adc ax, temp2 add temp1,25321 adc ax,13849 mov temp2, ax mov ah, al push ax push ax pop eax stosd mov es:[di+WIDTH_SCREEN-4], eax loop @b retn incfire endp copyvirtualscreen proc mov dx,IMPUT_STATUS_0 WaitVerticalSync:in al,dx test al,8 jz WaitVerticalSync WaitNotVerticalSync:in al,dx test al,8 jnz WaitNotVerticalSync mov cx,WIDTH_SCREEN*(HEIGHT_SCREEN-4)/4 xor si,si push ds mov ds,screen xor di,di push VGA_SEGMENT pop es rep movsd pop ds retn copyvirtualscreen endp end start P.S. Попробуйте найти ЧЕМ мой исходник отличается от исходника _edge
Полыхает огонь в душе моей. Компилировать uasm32 -bin -Fo napalm.com napalm.asm ЗЫ Да, линкер для com файлов UASM'у ненужен!