;/**************************************************************************** ;** MODULE: avidfill.asm ;** AUTHOR: Sami Tammilehto / Fennosoftec OY ;** DOCUMENT: ? ;** VERSION: 1.0 ;** REFERENCE: - ;** REVISED BY: - ;***************************************************************************** ;** ;** Assembler / Video (polygon filling) ;** ;****************************************************************************/ ;北北北北 _vid_drawpolylist(...) 北北北北 ;This call is obsolote. The correct call is to _draw_polylist. _vid_drawpolylist PROC FAR pop cx ;retoffset pop dx ;retsegment mov ax,0f001h push ax ;oflags push dx ;retsegment push cx ;retoffset jmp _draw_polylist ;draw.asm _vid_drawpolylist ENDP ;北北北北 _vid_drawfill(char *drawdata) 北北北北 ;entry: [drawdata]=pointer to fill data stream ; exit: - ;descr: This routine fills a polygon on screen according to instructions in ; the data stream. The 'nrm' stands for normal = flat shaded polygon. ; Stream format: {FILL-DATA} drawfill_progs LABEL WORD dw OFFSET drawfill_nrm dw OFFSET drawfill_grd _vid_drawfill PROC FAR CBEG call vidstart lfspar si,0 mov bx,ds:[si] cmp bx,1 ja @@1 add bx,bx add si,2 call drawfill_progs[bx] @@1: CEND _vid_drawfill ENDP ALIGN 4 leftside db 1111b,1110b,1100b,1000b rightside db 0001b,0011b,0111b,1111b middledot db 0001b,0010b,0100b,1000b ALIGN 16 vdf_leftx dd 0 vdf_lefta dd 0 vdf_rightx dd 0 vdf_righta dd 0 vdf_count dw 0 vdf_di dw 0 vdf_color db 0 ALIGN 16 vdfg_color1 dw 0 vdfg_color2 dw 0 vdfg_left dw 0 vdfg_right dw 0 vdfg_leftc dw 0 ;c & ca must be in this order for 32 bit vdfg_leftca dw 0 ;data transfer (seek for [32]) vdfg_rightc dw 0 vdfg_rightca dw 0 vdfg_lefts dw 0 vdfg_left4 dw 0 vdfg_buf db MAXCOLS dup(0) ;北北北北 drawfill_nrm 北北北北 ;entry: DS:SI=pointer to {NORMAL-FILL-DATA} stream ; exit: - drawfill_nrm PROC NEAR mov ax,fs:[si] mov cs:vdf_color,al mov bx,fs:[si+2] ;StartY add si,4 shl bx,1 mov ax,ds:_rows[bx] mov cs:vdf_di,ax ;es:vdf_di=dest jmp @@1 @@0: ret @@1: mov ax,fs:[si] add si,2 or ax,ax js @@0 jz @@11 mov eax,fs:[si] mov cs:vdf_leftx,eax mov eax,fs:[si+4] mov cs:vdf_lefta,eax add si,8 @@11: mov ax,fs:[si] add si,2 or ax,ax js @@0 jz @@12 mov eax,fs:[si] mov cs:vdf_rightx,eax mov eax,fs:[si+4] mov cs:vdf_righta,eax add si,8 @@12: mov ax,fs:[si] or ax,ax jz @@0 ;ERROR add si,2 mov cs:vdf_count,ax mov di,cs:vdf_di @@21: ;Fill loop ;; mov eax,cs:vdf_lefta add cs:vdf_leftx,eax mov eax,cs:vdf_righta add cs:vdf_rightx,eax ; mov dx,word ptr cs:vdf_leftx[2] mov ax,word ptr cs:vdf_rightx[2] ;dx=leftx, ax=rightx ; cmp ax,dx je @@20 jl @@22 xchg ax,dx @@22: dec dx ;don't fill the rightmost pixel mov bx,ax sar bx,2 mov cx,dx sar cx,2 sub cx,bx add di,bx mov bp,3 and bp,ax mov bh,cs:leftside[bp] mov bp,3 and bp,dx mov bl,cs:rightside[bp] mov dx,3c5h ;(di..si,bx) cmp cx,0 je @@29 ;end and beg in same byte ;left side mov al,bh out dx,al mov al,cs:vdf_color mov es:[di],al inc di dec cx mov ah,al ;middle jcxz @@24 mov al,0fh out dx,al mov al,ah mov bp,bx call faststosb mov bx,bp @@24: ;right side mov al,bl out dx,al mov al,ah mov es:[di],al jmp @@20 @@29: ;end and beg in same byte mov al,bl and al,bh out dx,al mov al,cs:vdf_color mov es:[di],al ;; @@20: mov di,cs:vdf_di add di,ds:_rowlen mov cs:vdf_di,di dec cs:vdf_count jnz @@21 jmp @@1 drawfill_nrm ENDP ;北北北北 drawfill_grd 北北北北 ;entry: DS:SI=pointer to {GOURAUD-FILL-DATA} stream ; exit: - drawfill_grd PROC NEAR mov bx,fs:[si+2] ;StartY add si,4 shl bx,1 mov ax,ds:_rows[bx] mov cs:vdf_di,ax ;es:vdf_di=dest jmp @@1 @@0: ret @@1: mov ax,fs:[si] add si,2 or ax,ax js @@0 jz @@11 mov eax,fs:[si] ;c&ca mov dword ptr cs:vdfg_leftc,eax ;[32] mov eax,fs:[si+4] mov cs:vdf_leftx,eax mov eax,fs:[si+8] mov cs:vdf_lefta,eax add si,12 @@11: mov ax,fs:[si] add si,2 or ax,ax js @@0 jz @@12 mov eax,fs:[si] ;c&ca mov dword ptr cs:vdfg_rightc,eax ;[32] mov eax,fs:[si+4] mov cs:vdf_rightx,eax mov eax,fs:[si+8] mov cs:vdf_righta,eax add si,12 @@12: mov ax,fs:[si] or ax,ax jz @@0 ;ERROR add si,2 mov cs:vdf_count,ax mov di,cs:vdf_di @@21: ;Fill loop ;; mov ax,cs:vdfg_leftca add cs:vdfg_leftc,ax mov ax,cs:vdfg_rightca add cs:vdfg_rightc,ax mov eax,cs:vdf_lefta add cs:vdf_leftx,eax mov eax,cs:vdf_righta add cs:vdf_rightx,eax ; mov dx,word ptr cs:vdf_leftx[2] mov ax,word ptr cs:vdf_rightx[2] mov bx,word ptr cs:vdfg_leftc mov cx,word ptr cs:vdfg_rightc ;dx=leftx, ax=rightx ; cmp ax,dx je @@20 jl @@22 xchg bx,cx xchg ax,dx @@22: dec dx ;don't fill the rightmost pixel mov cs:vdfg_color1,cx mov cs:vdfg_color2,bx mov cs:vdfg_left,ax mov cs:vdfg_right,dx ;set endpoint colors mov dx,3c5h ;end mov bl,byte ptr cs:vdfg_right test bl,1 jnz @@ef2 and bx,3 mov al,cs:middledot[bx] out dx,al mov bx,cs:vdfg_right shr bx,2 add bx,di mov al,byte ptr cs:vdfg_color2[1] mov es:[bx],al @@ef2: ;start mov bl,byte ptr cs:vdfg_left test bl,1 jz @@ef1 and bx,3 mov al,cs:middledot[bx] out dx,al mov bx,cs:vdfg_left shr bx,2 add bx,di mov al,byte ptr cs:vdfg_color1[1] mov es:[bx],al @@ef1: ;calc length & beg mov ax,cs:vdfg_left mov dx,cs:vdfg_right inc ax shr ax,1 mov cs:vdfg_lefts,ax dec dx shr dx,1 ; mov cx,ax shr cx,1 add di,cx ; mov cx,dx sub cx,ax inc cx ;cx=number of 2 byte blocks to fill cmp cx,0 jg @@2f2 ;ends only jmp @@20 @@2f2: push si mov ax,cs:vdfg_color1 sub ax,cs:vdfg_color2 jge @@2f3 neg ax mov bx,cx add bx,bx mul word ptr ds:_afilldiv[bx] neg dx jmp @@2f4 @@2f3: mov bx,cx add bx,bx mul word ptr ds:_afilldiv[bx] @@2f4: mov si,cx @@d0: ;dx=coloradder, cx=len (in 2 byte blocks) cmp dx,128 jge gouraud12 cmp dx,-128 jle gouraud12 jmp gouraud4 gouraud12: cmp dx,400 jge gouraud1 cmp dx,-400 jle gouraud1 jmp gouraud2 ;---------------------------------------------------------------- gouraud1 PROC NEAR ;1 pixel accuray sar dx,1 add cx,cx ; mov ax,cx shl cx,3 sub ax,cx ;ax=-cx*7 add ax,OFFSET @@vdfg_fcode mov bx,cs:vdfg_color2 jmp ax zzz=MAXCOLS REPT MAXCOLS+1 add bx,dx ;2 bytes mov cs:vdfg_buf[ (zzz and 3)*(MAXCOLS/4) + (zzz shr 2) ],bh ;5 bytes zzz=zzz-1 ENDM mov ax,bx ;2 bytes, 1 clock (filler) @@vdfg_fcode: push ds mov ax,cs mov ds,ax mov cx,si add cx,cx ; @@f1: mov al,00010001b test cs:vdfg_lefts,1 jz @@f2 mov al,01000100b @@f2: ; zzz=0 add cx,3 REPT 4 local l1 push cx shr cx,2 jz l1 push ax push di mov dx,3c5h out dx,al mov si,OFFSET vdfg_buf+zzz*(MAXCOLS/4) call fastmovsb pop di pop ax l1: pop cx dec cx rol al,1 adc di,0 zzz=zzz+1 ENDM ; @@f0: pop ds pop si jmp zzz20 gouraud1 ENDP ;---------------------------------------------------------------- gouraud2 PROC NEAR ;2 pixel accuray mov ax,cx shl cx,3 sub ax,cx ;ax=-cx*7 add ax,OFFSET @@vdfg_fcode mov bx,cs:vdfg_color2 jmp ax zzz=MAXCOLS REPT MAXCOLS+1 add bx,dx ;2 bytes mov cs:vdfg_buf[ (zzz and 1)*(MAXCOLS/2) + (zzz shr 1) ],bh ;5 bytes zzz=zzz-1 ENDM mov ax,bx ;2 bytes, 1 clock (filler) @@vdfg_fcode: push ds mov ax,cs mov ds,ax mov cx,si jcxz @@f0 ; @@f1: mov al,00110011b test cs:vdfg_lefts,1 jz @@f2 mov al,11001100b @@f2: ; mov si,OFFSET vdfg_buf push cx push di push ax inc cx shr cx,1 mov dx,3c5h out dx,al call fastmovsb pop ax pop di pop cx rol al,2 jnc @@f3 inc di @@f3: mov si,OFFSET vdfg_buf+MAXCOLS/2 shr cx,1 jz @@f0 mov dx,3c5h out dx,al call fastmovsb ; @@f0: pop ds pop si jmp zzz20 gouraud2 ENDP ;---------------------------------------------------------------- gouraud4 PROC NEAR ;4 pixel accuray cmp cx,4 jl gouraud2 sal dx,1 ; mov cs:vdfg_left4,cx shr cx,1 ;rescale inc cx ;one extra mov ax,cx shl cx,3 sub ax,cx ;ax=-cx*7 add ax,OFFSET @@vdfg_fcode mov bx,cs:vdfg_color2 sub bx,dx ;one extra jmp ax zzz=MAXCOLS REPT MAXCOLS+1 add bx,dx ;2 bytes mov cs:vdfg_buf[zzz],bh ;5 bytes zzz=zzz-1 ENDM mov ax,bx ;2 bytes, 1 clock (filler) @@vdfg_fcode: push ds mov dx,cs mov ds,dx mov cx,si ; @@f1: mov si,OFFSET vdfg_buf test cs:vdfg_lefts,1 jnz @@f3 inc cx @@f4: shr cx,1 jnc @@f5 mov dx,3c5h mov al,0fh out dx,al call fastmovsb @@f0: pop ds pop si jmp zzz20 @@f5: dec cx mov dx,3c5h mov al,0fh out dx,al call fastmovsb mov dx,3c5h mov al,03h out dx,al movsb pop ds pop si jmp zzz20 @@f3: mov dx,3c5h mov al,0ch out dx,al movsb jmp @@f4 gouraud4 ENDP ;---------------------------------------------------------------- zzz20: ;; @@20: mov di,cs:vdf_di add di,ds:_rowlen mov cs:vdf_di,di dec cs:vdf_count jnz @@21 jmp @@1 drawfill_grd ENDP ;北北北北 fastmovsb 北北北北 ;entry: DS:SI=pointer to source data ; ES:DI=pointer to destination (screen) ; CX=number of bytes to copy (MUST BE <512*4) ;exit: copies data like REP MOVSB but uses 32 bit moves and aligns ; destination to dword boundary. ALIGN 16 fastmovsb_bt LABEL WORD dw OFFSET fastmovsb_b0 dw OFFSET fastmovsb_b1 dw OFFSET fastmovsb_b2 dw OFFSET fastmovsb_b3 fastmovsb_b1: mov al,ds:[si] sub cx,3 mov es:[di],al mov ax,ds:[si+1] add si,3 mov es:[di+1],ax add di,3 jmp fastmovsb_b0 fastmovsb_b2: mov ax,ds:[si] sub cx,2 add si,2 mov es:[di],ax add di,2 jmp fastmovsb_b0 fastmovsb_b3: mov al,ds:[si] dec cx inc si mov es:[di],al inc di jmp fastmovsb_b0 ALIGN 16 fastmovsb_et LABEL WORD dw OFFSET fastmovsb_e0 dw OFFSET fastmovsb_e1 dw OFFSET fastmovsb_e2 dw OFFSET fastmovsb_e3 fastmovsb_e1: mov al,ds:[si] inc si mov es:[di],al inc di ret fastmovsb_e3: mov ax,ds:[si] mov es:[di],ax mov al,ds:[si+2] add si,3 mov es:[di+2],al add di,3 ret fastmovsb_e2: mov ax,ds:[si] add si,2 mov es:[di],ax add di,2 fastmovsb_e0: ret ALIGN 16 fastmovsb PROC NEAR ;copies CX bytes of data from DS:SI to ES:DI aligning destination ;si/di will point to the correct position after this (cx won't) cmp cx,4 jb @@4 mov bx,di and bx,3 add bx,bx jmp fastmovsb_bt[bx] fastmovsb_b0: mov bx,cx add bx,bx add bx,bx and bx,not 15 neg bx ;bx=-cx*8 add bx,OFFSET @@jmp jmp bx REPT 512 db 66h,8bh,84h,00h,00h ;mov eax,ds:[si+0000h] db 83h,0c6h,04h ;add si,4 db 66h,26h,89h,05h ;mov es:[di],eax db 81h,0c7h,04h,00h ;add di,0004h ENDM ;total 16 bytes @@jmp: mov bx,cx and bx,3 add bx,bx jmp fastmovsb_et[bx] @@4: mov bx,cx add bx,bx jmp fastmovsb_et[bx] fastmovsb ENDP ;北北北北 faststosb 北北北北 ;entry: ES:DI=pointer to destination (screen) ; AX=word fill (lo/hi byte MUST be same) ; CX=number of bytes to fill (MUST BE <512*4) ;exit: fills data like REP STOSB but uses 32 bit moves and aligns ; destination to dword boundary. ; NOTE: BX modified ALIGN 16 faststosb_bt LABEL WORD dw OFFSET faststosb_b0 dw OFFSET faststosb_b1 dw OFFSET faststosb_b2 dw OFFSET faststosb_b3 faststosb_b1: mov es:[di],al sub cx,3 mov es:[di+1],ax add di,3 jmp faststosb_b0 faststosb_b2: sub cx,2 mov es:[di],ax add di,2 jmp faststosb_b0 faststosb_b3: dec cx mov es:[di],al inc di jmp faststosb_b0 ALIGN 16 faststosb_et LABEL WORD dw OFFSET faststosb_e0 dw OFFSET faststosb_e1 dw OFFSET faststosb_e2 dw OFFSET faststosb_e3 faststosb_e1: mov es:[di],al inc di ret faststosb_e3: mov es:[di],ax mov es:[di+2],al add di,3 ret faststosb_e2: mov es:[di],ax add di,2 faststosb_e0: ret ALIGN 16 faststosb PROC NEAR ;fills CX bytes of data with AX to ES:DI aligning destination ;di will point to the correct position after this (cx won't) cmp cx,4 jb @@4 mov bx,di and bx,3 add bx,bx jmp faststosb_bt[bx] faststosb_b0: mov bx,ax shl eax,16 mov ax,bx ;eax=filler mov bx,cx add bx,bx and bx,not 7 neg bx ;bx=-cx*8 add bx,OFFSET @@jmp jmp bx REPT 512 db 66h,26h,89h,05h ;mov es:[di],eax db 81h,0c7h,04h,00h ;add di,0004h ENDM ;total 8 bytes @@jmp: mov bx,cx and bx,3 add bx,bx jmp faststosb_et[bx] @@4: mov bx,cx add bx,bx jmp faststosb_et[bx] faststosb ENDP