format MS COFF public EXPORTS section '.flat' code readable align 16 include 'vectors.inc' ;vectors functions constant macro swap v1, v2 { push v1 push v2 pop v1 pop v2 } BUF_STRUCT_SIZE equ 17 ;размер структуры, описывающей буфер BUF_MAX_COUNT equ 8 ;максимальное число буферов fun_draw_pixel dd drawpixel_scrn ;указатель на функцию рисования точки active_buffer: ;начало структуры активного буфера (буфера в который делается рисование фигур или текста) dd 0 ;указатель на буфер изображения dw 0 ; +4 left dw 0 ; +6 top dw 0 ; +8 w ширина буфера dw 0 ;+10 h высота буфера dd 0 ;+12 color цвет фона db 24 ;+16 bit in pixel глубина цвета (в данной версии еще не используется) rb BUF_STRUCT_SIZE * BUF_MAX_COUNT ;резервируем место для структур, описывающих буфера ;в активном буфере будет содержаться точная копия одной из этих структур active_buffer_left equ active_buffer+ 4 active_buffer_top equ active_buffer+ 6 active_buffer_w equ active_buffer+ 8 active_buffer_h equ active_buffer+10 active_buffer_color equ active_buffer+12 ;----------------------------------------------------------------------------- ;функция для выделения памяти ;input: ; ecx = size data ;otput: ; eax = pointer to memory mem_Alloc: push ebx mov eax,68 mov ebx,12 int 0x40 pop ebx ret ;----------------------------------------------------------------------------- ;функция для освобождения памяти ;input: ; ecx = pointer to memory mem_Free: push eax ebx cmp ecx,0 jz @f mov eax,68 mov ebx,13 int 0x40 @@: pop ebx eax ret ;функция рисующая точку сразу на экран (без участия буфера) align 4 drawpixel_scrn: bt bx,15 jc @f bt cx,15 jc @f ; cmp bx,300 ; jge @f ; cmp cx,300 ; jge @f int 0x40 @@: ret ;функция рисующая точку в активном буфере align 4 drawpixel_buf: bt bx,15 ;проверяем знак числа, если координата меньше 0 jc @f ;тогда точка в экран не попала, конец функции bt cx,15 jc @f cmp bx,word[active_buffer_w] ;проверяем координату точки, если больше ширины буфера jge @f ;тогда точка в экран не попала, конец функции cmp cx,word[active_buffer_h] jge @f push esi xor esi,esi ;тут будет указатель на пиксель из активного буфера mov si,word[active_buffer_w] ;ширина буфера по оси x imul esi,ecx ;size_x*y add esi,ebx ;size_x*y+x lea esi,[esi+esi*2] ;(size_x*y+x)*3 add esi,dword[active_buffer] ;ptr+(size_x*y+x)*3 mov word[esi],dx ;копируем зеленый и синий спектр ror edx,16 ;крутим цвет на 2 байта mov byte[esi+2],dl ;копируем красный спектр ror edx,16 ;крутим цвет назад pop esi @@: ret ;функция создающая новый буфер, принимает параметры нужные для структуры ;input: ; [esp+8] = bit on pixel, index created buffer ; [esp+10] = color ; [esp+14] = size: w,h ; [esp+18] = size: l,t align 4 buf_create: push ebp mov ebp,esp cmp byte[ebp+8],1 ;проверка правильности индекса создаваемого буфера jl .error_ind ;пользователь указал индекс меньше 1-цы, ... error :( cmp byte[ebp+8],BUF_MAX_COUNT ;проверка правильности индекса создаваемого буфера jg .error_ind ;пользователь указал индекс больше максимально возможного, ... error :( push eax ecx edi esi mov eax,dword[ebp+14] ;берем ширину и высоту буфера ror eax,16 ;меняем местами ширину и высоту, так будет удобнее при выводе для функции 7 mov dword[active_buffer_w],eax ;помещаем значения в структуру активного буфера xor ecx,ecx ;тут вычисляем сколько памяти нужно для этого буфера mov cx,ax ;берем нижний размер буфера shr eax,16 ;затираем нижний размер, в eax теперь только верхний размер, на месте нижнего imul ecx,eax ;умножаем высоту на ширину (может и наоборот ширину на высоту) imul ecx,3 ; 24 bit = 3, 32 bit = 4 ... work if only 24 call mem_Alloc ;просим память из системы mov dword[active_buffer],eax ;копируем указатель на полученую память в структуру активного буфера mov eax,dword[ebp+18] ;берем отступы слева и справа ror eax,16 mov dword[active_buffer_left],eax mov eax,dword[ebp+10] ;get color - берем цвет для фона mov dword[active_buffer_color],eax ;копируем всю структуру активного буфера, в память отведенную для буферов ;иначе если появится новый буфер, то он затрет собой активную структуру ;потому нужно дублировать эту информацию mov di,word[ebp+8] ;copy buffer struct and edi,0xff ;index <= 255 mov ecx,BUF_STRUCT_SIZE ;в ecx размер копируемых данных imul edi,ecx mov esi,active_buffer add edi,esi rep movsb ;повторяем копирование по байту, пока ecx станет не равно 0 push word[ebp+8] ;при создании буфера, в нем может быть мусор, call buf_clear ;потому чистим его фоновым цветом pop esi edi ecx eax .error_ind: pop ebp ret 14 ;функция установки активного буфера, если на входе 0 - то включается режим рисования на экран без буфера ;input: ; [esp+8] = index buffer (0-screen) align 4 set_active_buf: push ebp mov ebp,esp cmp word[ebp+8],0 jne @f .to_scrn: mov dword[fun_draw_pixel],drawpixel_scrn ;рисование в экран jmp .end_fun @@: cmp byte[ebp+8],BUF_MAX_COUNT ;if buffer index out of range jg .to_scrn mov dword[fun_draw_pixel],drawpixel_buf ;рисование в буфер push ecx esi edi mov si,word[ebp+8] ;copy buffer struct and esi,0xff ;index <= 255 mov ecx,BUF_STRUCT_SIZE imul esi,ecx mov edi,active_buffer add esi,edi rep movsb pop edi esi ecx cmp dword[active_buffer],0 ;if buffer is empty je .to_scrn .end_fun: pop ebp ret 2 ;функция очистки буфера фоновым цветом ;input: ; [esp+8] = index buffer (0-screen) align 4 buf_clear: push ebp mov ebp,esp push eax ebx ecx edi mov di,word[ebp+8] ;get pointer to buffer struct and edi,0xff ;index <= 255 imul edi,BUF_STRUCT_SIZE add edi,active_buffer ;edi = pointer to buffer struct cmp dword[edi],0 ;проверяем пустой указатель на буфер или нет je .no_draw ;если пустой, то выход xor ecx,ecx ;тут будет размер буфера в пикселях mov cx,word[edi+8] ;active_buffer_w] xor eax,eax mov ax,word[edi+10] ;active_buffer_h] imul ecx,eax ;ecx=x*y mov ebx,dword[edi+12] ;active_buffer_color] mov ax,bx shr ebx,16 ;imul ecx,3 ;rep stosb push dword[edi] ;save value in pointer pop edi ;get value in pointer @@: mov word[edi],ax add edi,2 mov byte[edi],bl inc edi loop @b .no_draw: pop edi ecx ebx eax pop ebp ret 2 ;функция рисующая содержимое буфера на экране, использует КОС функцию номер 7 ;input: ; [esp+8] = index buffer (0-screen) align 4 draw_buf: push ebp mov ebp,esp mov di,word[ebp+8] ;get pointer to buffer struct and edi,0xff ;index <= 255 imul edi,BUF_STRUCT_SIZE add edi,active_buffer ;edi = pointer to buffer struct mov eax,7 mov ebx,dword[edi] ;active_buffer] mov ecx,dword[edi+8] ;active_buffer_w] ;ecx = w*0xffff+h ror ecx,16 ;push word[edi+4] ;active_buffer_left] ;загрузка точки левого верхнего угла ;pop dx mov dx,word[edi+4] shl edx,16 ;push word[edi+6] ;active_buffer_top] ;загрузка точки левого верхнего угла ;pop dx mov dx,word[edi+6] int 0x40 pop ebp ret 2 ;функция очищающая память, занимаемую буфером ;input: ; [esp+8] = index buffer (0-screen) align 4 buf_delete: push ebp mov ebp,esp mov cx,word[ebp+8] ;get pointer to buffer struct and ecx,0xff ;index <= 255 imul ecx,BUF_STRUCT_SIZE add ecx,active_buffer ;edi = pointer to buffer struct push dword[ecx] ;save value in pointer pop ecx ;get value in pointer call mem_Free pop ebp ret 2 ;функция рисующая линию ;input: ; [esp+8] = p0 ; [esp+12] = p1 ; [esp+16] = color loc_0 equ byte[ebp-4] loc_1 equ word[ebp-6] loc_2 equ word[ebp-8] align 4 line_brs: push ebp mov ebp,esp sub esp,6 ;=1+2*2 pushad ;eax ebx ecx edx si di mov edx,dword[ebp+16] ;--- mov ax,word[ebp+14] ;y1 ; cmp ax,0 ;if y1<0 return ; jl .coord_end ; cmp word[ebp+10],0 ;if y0<0 return ; jl .coord_end sub ax,word[ebp+10] ;y1-y0 bt ax,15 jae @f neg ax inc ax @@: mov bx,word[ebp+12] ;x1 ; cmp bx,0 ;if x1<0 return ; jl .coord_end ; cmp word[ebp+8],0 ;if x0<0 return ; jl .coord_end sub bx,word[ebp+8] ;x1-x0 bt bx,15 jae @f neg bx inc bx @@: mov byte[ebp-4],byte 0 ;bool steep=false cmp ax,bx jle @f mov byte[ebp-4],byte 1 ;bool steep=true swap word[ebp+8],word[ebp+10] ;swap(x0, y0); swap word[ebp+12],word[ebp+14] ;swap(x1, y1); @@: mov ax,word[ebp+8] ;x0 cmp ax,word[ebp+12] ;if(x0>x1) jle @f swap word[ebp+8],word[ebp+12] ;swap(x0, x1); swap word[ebp+10],word[ebp+14] ;swap(y0, y1); @@: ; int deltax si ; int deltay di ; int error ebp-6 ; int ystep ebp-8 mov ax,word[ebp+8] ;x=x0 mov si,word[ebp+12] ;x1 sub si,ax ;deltax = x1-x0 mov bx,si shr bx,1 mov loc_1,bx ;error = deltax/2 mov ax,word[ebp+10] ;y=y0 mov di,word[ebp+14] ;y1 mov loc_2,word -1 ;ystep = -1 cmp ax,di ;if (y0